Suppose we need to run application in screen and keep it running when screen exits. The following command does the job, but only if "sleep 1" is appended to it. Why it does not work without "sleep 1"?

screen -d -m -L sh -c 'DISPLAY=:0 nohup zenity --info --text test >/dev/null 2>/dev/null &'
  • 1
    which place do you add the sleep – Bharat Sep 5 '18 at 4:32
  • @Bharat in the end – Igor Liferenko Sep 5 '18 at 5:03

This seems to be a timing problem, in that nohup does not have time enough to disable signals before it is signaled by one of the parents. You can see this by adding strace -o /tmp/s -ff in front of the screen command and then in one of the log files /tmp/s.* you see

access("/bin/nohup", X_OK)              = 0
stat("/bin/nohup", {st_mode=S_IFREG|0755, st_size=36696, ...}) = 0
--- SIGHUP {si_signo=SIGHUP, si_code=SI_KERNEL} ---
+++ killed by SIGHUP +++

You can simplify the startup. This works for me without the need for &.

DISPLAY=:0 screen -d -m -L nohup zenity --info --text test 

Another solution seems to be to ask the parent shell to use job control. This seems to make it either disable SIGHUP to the background, or otherwise wait for the child nohup to be further on before exiting itself. Using sh -cm instead of sh -c on your original command should work better. For example, this works for me

screen -d -m -L sh -cm 'nohup zenity --info --text test >&/dev/null & echo'

whereas the -c verson does not. bash has a disown command that protects a background job from SIGHUP, if using job control, but you don't seem to need it even without nohup as this works too, without leaving a screen process running:

screen -d -m -L sh -cm 'zenity --info --text test >&/dev/null </dev/null & echo'
  • There are other commands in the real script after zenity, so it is impossible that those commands will be executed if & is not used. – Igor Liferenko Sep 10 '18 at 2:16
  • Is there a way to add a while loop or something after the & to ensure that nohup had started before proceeding further? – Igor Liferenko Sep 10 '18 at 2:17
  • Use nohup as the all-encompassing command, eg: nohup sh -c 'zenity --info --text test & date >/tmp/out' – meuh Sep 10 '18 at 18:36
  • 1
    I found another way that works: use all-encompassing command, but instead of nohup, use nohup-noout wrapper shell script: nohup "$@" >/dev/null 2>/dev/null (then nohup.out file will not be created). – Igor Liferenko Sep 11 '18 at 9:06
  • 1
    A small correction: getting rid of nohup.out invalidates the -L flag of screen, so instead of saving screen's log with -L, just gobble screen's log by adding -Logfile /dev/null and use nohup.out in place of former screenlog.0 – Igor Liferenko Sep 12 '18 at 5:57

Using nohup as all-encompassing command is impossible because it does not allow to get rid of nohup.out without suppressing all the output, and using nohup.out instead of screenlog.0 is impossible because nohup.out does not preserve carriage return.

Instead of using nohup, use shell's trap. So, command in OP becomes:

screen -d -m -L sh -c 'trap "" HUP; DISPLAY=:0 zenity --info --text test >/dev/null 2>/dev/null &'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.