我正在通过SSH(Putty)在Linux机器上工作。 我需要在晚上期间让一个进程一直运行,所以我认为我可以在命令末尾使用&符号将进程放入后台并将stdout重定向到文件中。
令我惊讶的是,这并不起作用。 一旦关闭Putty窗口,进程就会停止。
我该如何防止这种情况发生?
我正在通过SSH(Putty)在Linux机器上工作。 我需要在晚上期间让一个进程一直运行,所以我认为我可以在命令末尾使用&符号将进程放入后台并将stdout重定向到文件中。
令我惊讶的是,这并不起作用。 一旦关闭Putty窗口,进程就会停止。
我该如何防止这种情况发生?
请查看"nohup"程序。
nohup command > /dev/null 2>&1 &
命令在后台运行程序,且不会生成任何标准输出或错误输出(也不会产生 nohup.out
文件)。 - KCDnohup
无法帮助。是否有一种方法可以通过Ctrl+Z
/bg
来解决问题? - Sergeynohup
无法解决问题,因为它不能防止SIGHUP信号,只是默认忽略它,这并不总是有效。由于我没有screen
、tmux
、at
或类似的工具,我需要一种在shell级别上确保将程序与ctty分离的方法。我找到的唯一方法是使用ssh -T remote '(program&)&'
启动程序的hack方式,这使得在交互式的ssh
会话中无法将程序放入后台。 - Tino我建议使用GNU Screen。它可以让你断开与服务器的连接,同时所有进程仍然在运行。在我了解它之前,我不知道该怎么生活。
screen
。 - mabalenk当会话关闭时,进程将收到SIGHUP信号,但显然未捕获。您可以在启动进程时使用nohup
命令或在启动进程后使用bash内置命令disown -h
来防止发生这种情况:
> help disown
disown: disown [-h] [-ar] [jobspec ...]
By default, removes each JOBSPEC argument from the table of active jobs.
If the -h option is given, the job is not removed from the table, but is
marked so that SIGHUP is not sent to the job if the shell receives a
SIGHUP. The -a option, when JOBSPEC is not supplied, means to remove all
jobs from the job table; the -r option means to remove only running jobs.
daemonize?nohup?SCREEN?(tmux ftw,screen is junk ;-))
自从应用程序起源以来,只要像其他应用程序一样做就可以了——双重fork。
# ((exec sleep 30)&)
# grep PPid /proc/`pgrep sleep`/status
PPid: 1
# jobs
# disown
bash: disown: current: no such job
嘭!完成了 :-) 我在各种应用程序和老机器上无数次地使用了这个。您可以与重定向等结合使用,以在您和进程之间创建一个私有通道。
将其创建为coproc.sh:
#!/bin/bash
IFS=
run_in_coproc () {
echo "coproc[$1] -> main"
read -r; echo $REPLY
}
# dynamic-coprocess-generator. nice.
_coproc () {
local i o e n=${1//[^A-Za-z0-9_]}; shift
exec {i}<> <(:) {o}<> >(:) {e}<> >(:)
. /dev/stdin <<COPROC "${@}"
(("\$@")&) <&$i >&$o 2>&$e
$n=( $o $i $e )
COPROC
}
# pi-rads-of-awesome?
for x in {0..5}; do
_coproc COPROC$x run_in_coproc $x
declare -p COPROC$x
done
for x in COPROC{0..5}; do
. /dev/stdin <<RUN
read -r -u \${$x[0]}; echo \$REPLY
echo "$x <- main" >&\${$x[1]}
read -r -u \${$x[0]}; echo \$REPLY
RUN
done
然后
# ./coproc.sh
declare -a COPROC0='([0]="21" [1]="16" [2]="23")'
declare -a COPROC1='([0]="24" [1]="19" [2]="26")'
declare -a COPROC2='([0]="27" [1]="22" [2]="29")'
declare -a COPROC3='([0]="30" [1]="25" [2]="32")'
declare -a COPROC4='([0]="33" [1]="28" [2]="35")'
declare -a COPROC5='([0]="36" [1]="31" [2]="38")'
coproc[0] -> main
COPROC0 <- main
coproc[1] -> main
COPROC1 <- main
coproc[2] -> main
COPROC2 <- main
coproc[3] -> main
COPROC3 <- main
coproc[4] -> main
COPROC4 <- main
coproc[5] -> main
COPROC5 <- main
然后你就可以生成任何内容了。<(:) 通过进程替换打开一个匿名管道,这个进程会死亡,但是由于你仍然持有管道的句柄,所以管道仍然存在。我通常使用 sleep 1
而不是 :
,因为它略微有点竞态条件,并且如果运行一个真正的命令(例如 command true
),则永远不会发生“文件忙”错误。
“heredoc sourcing”:
. /dev/stdin <<EOF
[...]
EOF
这适用于我尝试过的每个 shell,包括 busybox/etc (initramfs)。我以前从未见过这样做,是在探索时独立发现的,谁知道源码可以接受参数?但如果有这样的东西存在,它通常作为一种更可管理的 eval 形式。
ssh myhost "((exec sleep 500)&) >/dev/null"
- anthonyrisingerssh myhost 'sleep 500 >&- 2>&- <&- &'
TMTOWTDI ;) - tbc0nohup blah &
用你的进程名称替换blah!
就我个人而言,我喜欢使用“批处理”命令。
$ batch
> mycommand -x arg1 -y arg2 -z arg3
> ^D
这个东西将其置于后台,然后将结果发送给您。它是cron的一部分。
Usage: daemonize [-abchptxV][-d dir][-e err][-i in][-o out][-s sigs][-k fds][-m umask] -- command [args...]
-V print version and exit
-a output files in append mode (O_APPEND)
-b both output and error go to output file
-c create output files (O_CREAT)
-d dir change to given directory
-e file error file (standard error - /dev/null)
-h print help and exit
-i file input file (standard input - /dev/null)
-k fd-list keep file descriptors listed open
-m umask set umask (octal)
-o file output file (standard output - /dev/null)
-s sig-list ignore signal numbers
-t truncate output files (O_TRUNC)
-p print daemon PID on original stdout
-x output files must be new (O_EXCL)
daemonize
的源代码,请仍然可以通过发送电子邮件联系我(firstname dot lastname at gmail dot com)。daemonize-1.10.tgz
在packages子目录中提供。对于大多数进程,您可以使用这个古老的Linux命令行技巧来伪守护程序:
# ((mycommand &)&)
例如:# ((sleep 30 &)&)
# exit
然后打开一个新的终端窗口并输入以下命令:
# ps aux | grep sleep
将展示sleep 30
仍在运行。
你所做的是将进程作为子进程的子进程启动,当你退出时,通常会触发进程退出的nohup
命令不会向下级传递到孙子进程,使其成为一个孤儿进程,仍然在运行。
我更喜欢这种"设置并忘记"的方法,无需处理nohup
、screen
、tmux、I/O重定向或任何那些东西。
nohup
非常适合将详细信息记录到文件中。但是,当它进入后台时,如果您的脚本要求密码,则无法为其提供密码。我认为您应该尝试screen
。这是一个实用程序,您可以使用yum在Linux发行版上安装,例如在CentOS上使用yum install screen
,然后通过putty或其他软件访问您的服务器,在shell中键入screen
。它将在putty中打开screen [0]。完成您的工作。您可以在同一putty会话中创建更多的screen[1],screen[2]等。
您需要了解的基本命令:
启动screen
创建下一个screen
移动到您创建的下一个screen
分离
在工作期间关闭putty。下次通过putty登录时输入
重新连接到您的screen,您可以看到进程仍在screen上运行。要退出screen,请键入#exit。
有关更多详细信息,请参见man screen
。
yum
是正确的工具,但当你不知道发行版时,使用它并不好。你应该明确哪些发行版可以使用 yum
安装 screen
。 - tymik