I have some scripts that I'm developing on a vm but sometimes needs to run on a production server to be properly tested.
I need the output from the scripts for debugging so I've tinkered together the following solution:
function test_remote() {
scp $1 Prod:/home/xxx/tmp/
n=${1:t:r}
f=${1:t}
cmd="ssh Prod \"/usr/bin/php /home/xxx/tmp/$f\" > /home/xxx/tests/$n-remote-test.html"
eval ${cmd}
ssh Prod "rm /home/xxx/tmp/$f"
echo "done"
}
which I have placed in my .zshrc file
I would like to run it in the background using
test_remote path_to_file/php_file.php &
but as I do I always get the following result
[1] + 12996 suspended (tty input) test_remote path_to_file/php_file.php
if I resume it with bg it just repeats the same message
When a background process attempts to read from standard input, it is sent a signal which suspends it. This is so the user can bring the process to the foreground again and provide the necessary input.
If no input needs to be provided, you can redirect the standard input from
/dev/null
, either when callingtest_remote
or incmd
.SSH is reading from its standard input, which is the terminal. It does this even if the program on the remote side doesn't try to read from its standard input, because it has no way to know that the remote side won't try (and also because the user could press a key such as Ctrl+C which the server side would translate to sending a signal).
There can only sensibly be a single process reading from the terminal: if there were multiple processes, which one would receive each key press? (When that does happen, the effect is that each byte goes more or less randomly to a different process.) The terminal management framework in the kernel ensures that (under normal circumstances) only the foreground process receives terminal input. If a background process tries to read from the terminal, it receives a SIGTTIN signal and the default action for that signal is to suspend the process. “12996 suspended (tty input)” is the shell letting you know that process 12996 was suspended by a SIGTTIN.
A generic way to avoid that, with any background command that might try to read from its standard input, is to redirect its standard input from somewhere else, for example
/dev/null
.With the SSH client, you can use the
-n
option to achieve the same effect. You can also use the-f
option to tellssh
to go to the background after reading a password; this is useful if you have to use a password, but you should use keys instead if at all possible. These options have the downside that the background process is not a shell job so you can't wait for its termination and get.Why on earth are you using
eval
? Just write