For your command to detect eof
, it has to read from stdin. So presumably it is expecting some input. So it sounds like what you need is not an empty input (/dev/null
is exactly meant for that), but input that never comes.
It can be simulated with a pipe where nobody is ever going to write on the other end like:
sleep 999999999 | the-command
Or to avoid having to run that extra sleep
command, it could be done with a named pipe:
fifo=$(mktemp -u) &&
mkfifo "$fifo" &&
(rm "$fifo" && the-command <&3 3<&- &) 3<> "$fifo"
Here using an intermediary file descriptor to work around the fact that the shell connects stdin to /dev/null
implicitely when you start a command with &
(unless you add an explicit stdin redirection like our <&3
here).
On Linux (and probably on Linux only), you can also do:
the-command < /dev/fd/1 3>&1 > /dev/null | :
/dev/fd/1
where fd 1 is connected to a pipe, on Linux, behaves like a named pipe. That is, when you open it in read mode, you get the reading end of the pipe.
So above, fd 0 will be connected to the reading end of a pipe whose other end is on the fd 3 of the-command
. Because the-command
is not going to write anything on its fd 3, any read
attempt on fd 0 will block (or a non-blocking read will return with there's nothing to read yet, or a select/poll will return nothing to read either as the-command
is probably doing if it's doing anything else than waiting for input that never comes).
remote log in to linux over the network via SSH ... log out of linux; type exit
in the putty SSH terminal
Can someone give me a practical scenario where nohup
would be used?
Sure. Assuming your shell is bash (see below why), instead of typing exit
or ^D
, type ~.
at the beginning of a line, which will cause your ssh client to disconnect:
$ ssh localhost
ssh$ sleep 3600 &
[1] 5765
ssh$ ~.
ssh$ Connection to localhost closed.
$ ps 5765
PID TTY STAT TIME COMMAND
You can use your program instead of sleep
; and instead of disconnecting via ~.
, you can kill your ssh client or crash the machine it runs on. You want your process to survive this? Use nohup
;-)
Breaking the connection will cause the server process which manages its other end to exit, causing the kernel (any Unix/Linux kernel) to tear down the pseudo-terminal ssh had created, and to send a SIGHUP
signal to the session leader (the bash shell), which according to the bash manual:
The shell exits by default upon receipt of a SIGHUP
. Before exiting,
an interactive shell resends the SIGHUP
to all jobs, running or
stopped. Stopped jobs are sent SIGCONT
to ensure that they receive the
SIGHUP
.
Many people confuse this bash feature with a) the regular job control thing implemented by the kernel, which will only send a SIGCONT
/SIGHUP
pair to the stopped, not to the running jobs [1] and b) another bash feature (shopt -s huponexit
) which causes a login bash shell to send a SIGHUP
to its jobs even when exiting normally (eg. via exit
).
[1] a stopped job is a job (= process group) which contains at least one stopped process. A process is stopped as an effect of the default action of a signal like SIGTSTP
, SIGSTOP
, SIGTTIN
or SIGTTOU
. Processes which are "sleeping" on a blocking system call like read
, nanosleep
, select
, etc are not considered stopped, but running.
Why nohup
may not always help
nohup
just sets the disposition of SIGHUP
to ignore and does some redirections, it does not guarantee that the process will not be killed by other ways.
a) If the nohup ..
job is stopped, an interactive bash will also send it a SIGTERM
signal, not just a SIGHUP
/SIGCONT
pair:
If an attempt to exit bash is made while jobs are stopped [...] the shell prints a warning message [...] If a second attempt to exit is made without an intervening command, the shell does not print another warning, and any stopped jobs are terminated.
[terminated = sent a SIGTERM
signal; this is another ksh/bash feature, not present in all shells]
All this can be worked around by simple tricks like double-forks and by creating a new session with setsid(1)
, but
b) systemd
may also "clean up" a logged-out session by forcefully killing (with SIGTERM
followed by SIGKILL
) any left-over processes if its KillUserProcesses
setting is on, which is the default in some distros.
Best Answer
If you just want to write a single
y
to the stdin of the process, you can do this:If you want to keep writing
y
for every prompt that comes up, the coreutilyes
exists for exactly this purpose -- it will keep writing whatever you tell it to to stdout. Its default is to output "y", so you can just:but if you need something else you can pass it as an argument