我复制了一段 Bash 到后台远程执行的 ssh 命令:
ssh user@remote <<CMD
some process <&- >log 2>error &
CMD
有什么<&-
作用?
我的猜测是它与< /dev/null
我的下一个理解是,需要关闭三个主要文件描述符(stdin
、stdout
、 )以防止:stderr
- 正在后台运行的作业和正在退出的脚本——有什么冲突吗?
- 当终端关闭时,所有从终端接受 stdin 的进程都会关闭吗?
答案1
<&-
不是相当与 相同的事情< /dev/null
。<&-
关闭 fd 0,而< /dev/null
从 device 重定向它/dev/null
,它从不提供任何数据,并且总是在读取时给出 EOF。区别主要在于,read(2)
来自关闭 FD(本<&-
例)的调用将出现 EBADF 错误,而来自空重定向 FD 的调用将不返回读取的字节(文件结束条件)。如果您的程序从不从标准输入读取数据,那么区别并不重要。
如果您要在后台运行某些内容,则关闭 FD 是一个很好的做法,因为如果后台进程尝试从 TTY 读取任何内容,它就会挂起。不过,这个例子并没有完全处理它应该处理的所有事情;理想情况下,在某个地方会有一个nohup
orsetsid
调用,以完全解除后台进程的关联。
答案2
看man bash
:
[n]<&word
用于复制输入文件描述符。如果
word
扩展为一位或多位数字,则 表示的文件描述符n
将成为该文件描述符的副本。如果 中的数字word
未指定打开以供输入的文件描述符,则会发生重定向错误。如果 word 的计算结果为-
,则文件描述符n
被关闭。如果n
未指定,则使用标准输入(文件描述符 0)。
答案3
<&-
关闭标准输入。
这一般形式,由 POSIX 定义, 是:
[n]<&word
其创建文件描述符的目的n
是由 表示的文件描述符的副本word
。如果n
省略,则假定为标准 in ,如果word
是-
,则文件描述符n
将被关闭。
它与 不同</dev/null
,因为在 的情况下</dev/null
,标准输入仍然打开,并被重定向到其他地方。
您需要关闭附加到 ssh 套接字的进程的所有文件描述符,否则 ssh 会话无法关闭。
您可以在远程计算机上运行该命令,而无需将其附加到 ssh 会话,方法是使用屏幕或者多路复用器:
ssh user@remote 'screen -S test -d -m command'