0

Im trying to run a command in screen, but prevent it from ending the session once i kill the child process with Ctrl-C while in screen, much like this: https://unix.stackexchange.com/a/47279/79125, but in my case the command is run as different user, and i would like to get back a shell when i Ctrl-C the child process. Here are my unsuccessful attempts

$ screen -S mySession -X screen -t tab3   sh  -c ' su - appuser -c "cd /appdir/bin; ./app start; bash"'

$ screen -S mySession -X screen -t tab6   su - appuser -c "sh -c 'cd /appdir/bin; ./app start; exec bash'"

$ screen -S mySession -X screen -t tab6   sh -c "su - appuser -c 'cd /appdir/bin; ./app start; exec bash'" 

$ screen -S mySession -X screen -t tab6   sh -c "su - appuser -c 'cd /appdir/bin; ./app start; exec bash'; su - someuser -c 'exec bash'"
mike-m
  • 545
  • will nohup help here? – George Udosen Aug 05 '17 at 18:39
  • @george mind giving an example i can test? my use case is to start the tab with the command, and enter the screen tab later and stop the command without loosing the session tab – mike-m Aug 05 '17 at 19:20
  • Which user shall the shell belong to? – Hauke Laging Aug 05 '17 at 19:36
  • @HaukeLaging in the tab , the parent user (root) runs a command as appuser, su - appuser -c "sh -c 'cd /appdir/bin;........ , i would like this session as appuser to not disappear when i Ctr-C the app thats running. – mike-m Aug 05 '17 at 19:40

2 Answers2

1

signal handling

The problem is that both the outer shell and the app receive the signal. The outer shell may not simply ignore the signal because so would its child processes.

The solution is using a signal handler which passes the signal on to the app:

bash -cm 'trap "kill -INT \$KILLPID" int; /bin/sleep 5 & KILLPID=$!; fg; /bin/echo foo'

The -m is needed because job control ist deactivated by default for non-interactive shells.

The full command (not tested):

screen [...]  su - appuser -c bash -c 'cd /appdir/bin; ./app start & KILLPID=$!; trap "kill -INT $KILLPID" int; fg; bash'
Hauke Laging
  • 90,279
1

You need to create the tabs first, and then tell screen to run something in them, using -X stuff.

For example:

#!/bin/bash

# start a new detached screen, create windows named tab3 and tab6
# with appuser's $SHELL running in them, running as user "appuser".
screen -c /dev/null -d -m -S mySession
screen -c /dev/null -S mySession -X screen -t tab3 sudo -u appuser -i
screen -c /dev/null -S mySession -X screen -t tab6 sudo -u appuser -i

# as root, you could use `su - appuser`, instead of sudo but that
# would ask for a password if this is run as non-root user.  sudo
# can be configured to not ask for a password if required.   

# run some programs in the already-created tab3 and tab6
# using screen's "stuff" command.
screen -c /dev/null -S mySession -p tab3 -X stuff $'top\n'
screen -c /dev/null -S mySession -p tab6 -X stuff $'htop\n'

You can attach to that screen with, e.g., screen -S mySession -d -RR. If you quit from either top or htop in their respective tabs, those tabs will NOT close, they'll return to appuser's shell prompt.

I'm using -c /dev/null here to stop screen from reading my ~/.screenrc, which creates a bunch of tabs and sets everything up as I want it. Or used to want it, I switched to tmux about a year ago after using screen for decades.

Another way to do this is to create a new screenrc file with the required screen and stuff commands in it, and then just run screen -c /path/to/newscreenrc

cas
  • 78,579
  • the problem was not running something in them, but rather, running something in them as a different user, and not loosing that session tab if i killed that child process, but instead get the shell back as that user i was running as. – mike-m Aug 06 '17 at 15:59
  • that's pretty much exactly what the example script above does. – cas Aug 06 '17 at 16:15
  • Ah, true, i think i overlooked the sudo -u above. elegant too. – mike-m Aug 06 '17 at 16:18