我发现了 bash 中一些我以前从未遇到过的奇怪行为。
看来,如果我将 stderr 和 stdout 重定向到一个进程的文件,然后我 tail 该文件并向 tail 进程发送 ctrl-c 中断,那么原始进程就会停止!
例子:
$ ./ec2_backup.sh > backup.out 2>&1 &
$ tail -f backup.out
pending
Checking instance i-a3214dc7
running
Instance i-a3214dc7 is running.
^C
[1]+ Stopped ./ec2_backup.sh > backup.out 2>&1
环境是通过Mac通过ssh登录的Ubuntu 10.04 bash终端。
有人能向我解释一下吗?
谢谢!
答案1
我不认为尾部的CTRL+C是这里的问题。我敢打赌,作业在尾部运行时会停止,但您看不到它,因为 bash 直到向您显示 shell 提示符之前才会告诉您这些事情(此行为是默认行为,可以使用 进行更改set -b
)。
我认为正在发生的事情是你的工作是使用 TTY 做一些事情。每当后台应用程序尝试从 TTY 读取时,它都会收到一个SIGTTIN
。这是因为它在后台,不应该与用户交互,因此导致SIGTTIN
进程被停止(不是被杀死,而是被停止)。此外,如果您已stty tostop
设置并且应用程序尝试将任何输出写入 TTY,那么它也将被停止。
即使您重定向了 stdin 和 stdout,后台应用程序仍有可能找出它们所在的 TTY 并尝试直接访问它。
编辑(回答您的评论):
我在后台 ssh 上也遇到过类似的问题。我不知道它为什么尝试访问 TTY,但它确实访问了,并且因此收到了 SIGTTIN。
您可以尝试将您的命令包装在其中script
。
script -c ./ec2_backup.sh /dev/null &>/dev/null </dev/null &
脚本创建一个 TTY 供进程交互,并将此 TTY 重定向到 STDIN/STDOUT 或从 STDIN/STDOUT 重定向。现在,那些认为自己正在与完整 TTY 交互的应用程序实际上只与简单的 STDIN 和 STDOUT 管道交互。这样,您现在可以将 STDIN 和 STOUT 重定向到,/dev/null
而后台应用程序将无法尝试获取 TTY(并SIGTTIN
从尝试这样做中获取)。
答案2
使用
nohup ./ec2_backup.sh > backup.out 2>&1 &