showkey
showkey

Reputation: 338

Nohup take no effect when to close the terminal end the process running in background?

nohup command & can keep a command running after closing the terminal. I want to play all mp3 music in directory Music.

ls Music/*mp3 |xargs -d "\n" mplayer  

ls Music/*mp3 can list all mp3 files in directory Music, send it via pipe with xargs, -d "\n" is to treat blanks in the filenames.

I want to redirect all stdout and stderr into /dev/null, and run it in the background.

ls Music/*mp3 |xargs -d "\n" mplayer > /dev/null 2>&1 &

This works fine, but I want it running after closing the terminal.

nohup ls Music/*mp3 | xargs -d "\n" mplayer > /dev/null 2>&1 &
ls Music/*mp3 | xargs -d "\n" nohup mplayer > /dev/null 2>&1 &
ls Music/*mp3 | nohup xargs -d "\n" mplayer > /dev/null 2>&1 &

When I close the terminal, the process running in the background ends.
Why does nohup not take effect in any of the above three commands? How can I make it take effect?

disown can solve the issue, but I would like a solution using nohup.

ls Music/*mp3 | xargs -d "\n" mplayer > /dev/null 2>&1 & disown

Upvotes: 9

Views: 8011

Answers (5)

LitileXueZha
LitileXueZha

Reputation: 620

You should wait nohup transfer the parent process to PID 1.

$ nohup [YOUR COMMAND] 2>&1 &
nohup: appending output to 'nohup.out'
$ #usually this appeared then you can exit safely
$ sleep 1
$ exit

Exit too early may cause the parent process of command and itself be killed.

Upvotes: 0

dimo414
dimo414

Reputation: 48794

nohup command means "run command and ignore HUP signals".

So before we can effectively use nohup we need to ask: when and how is SIGHUP sent? As the Bash manual says, "Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped.". It goes on to say that the proper way to suppress this behavior is with disown. I realize you are asking about nohup, but it's worth calling out that disown is the intended and easier way to accomplish what you want. Note that disown is not equivalent to nohup.

The reason nohup is tricky to work with here is because it applies to a single process, whereas & creates a background job of a whole command pipeline, which can consist of multiple processes. This means you need to nohup each command in the pipeline in order to ensure that the individual commands don't receive a SIGHUP, e.g.:

$ nohup ls Music/*mp3 2>/dev/null | nohup xargs -d "\n" nohup mplayer &> /dev/null &

This should work, though I haven't tested it with these specific commands. If it doesn't, it's likely another process that you aren't starting directly is still receiving a SIGHUP. This is harder to address, which is exactly why we have disown.

manishg's suggestion is also reasonable; by moving the pipeline into a separate process you can nohup that process, which should in turn prevent a SIGHUP from reaching its children when your shell closes.


All that said, you don't need ls and xargs here in the first place; find can be used to similar effect and will simplify reasoning about the command. Try:

$ nohup find Music -maxdepth 1 -name '*mp3' -exec mplayer {} + &> /dev/null &

Upvotes: 10

showkey
showkey

Reputation: 338

There are two way to close the terminal.
exit way:

Input exit in terminal and click enter.

cross way:
Click the cross at the upper right corner.

To illustrate them with same png file. enter image description here nohup can take effect only with exit way for all the following command(checked everyone at least three times in terminal).

ls Music/*mp3 |xargs -d "\n" nohup mplayer  > /dev/null 2>&1 &
ls  Music/*mp3 | nohup  xargs  -d  "\n"  mplayer  > /dev/null  2>&1  &
nohup ls Music/*mp3 2>/dev/null | nohup xargs -d "\n" nohup mplayer &> /dev/null &
nohup find Music -maxdepth 1 -exec mplayer {} \; &> /dev/null &
nohup mplayer Music/*mp3 &> /dev/null &

A little bug for both nohup sh -c and nohup bash -c:

nohup sh -c 'ls  Music/*mp3 |  xargs  -d  "\n"  mplayer' &
[1] 4581
nohup: ignoring input and appending output to 'nohup.out'
nohup bash -c 'ls  Music/*mp3 |  xargs  -d  "\n"  mplayer' &
[1] 16831
nohup: ignoring input and appending output to 'nohup.out'

When to close terminal with cross way ,music will not play in background for all above command.

The command ending with disown will go on to play the music in background with whatever way (exit or cross way).
It is better to exec disown command in order to go on to play music in background after closing the terminal.

Upvotes: 1

Socowi
Socowi

Reputation: 27185

I want to play all mp3 music in directory Music.

Usually, you don't need ls or xargs for that.
You can simplify your whole pipeline to mplayer Music/*mp3 ✱.
This is not only safer for special filenames, but also solves your problem with nohup:

nohup mplayer Music/*mp3 &> /dev/null &
✱ There is only one case where this command fails and `ls * | xargs` succeeds. If you have a very large number of mp3 files you might run into the command line length limit. The limit in bytes is given by `getconf ARG_MAX`. On my system it is 2097152, meaning you would need at least 8000 files assuming a maximum file name length of 255 bytes. With shorter file names, you can have even more files. For instance, if your mp3 files are usually around 40 bytes long, you can use more than 44000 files.

Upvotes: 4

manishg
manishg

Reputation: 9818

nohup doesn’t work like this with pipes. use the following way:

nohup sh -c 'ls  Music/*mp3 |  xargs  -d  "\n"  mplayer' &

Upvotes: 0

Related Questions