3

我很清楚重复问题的存在。但是该问题已被标记为已回答,我认为它根本无法回答原始问题。

$ nohup command即使 nohup 的父进程(shell)死亡,它也会继续执行命令。更多信息在这里:nohup 和 & 之间有什么区别

在 Win32 api 的情况下,我看到行当系统终止进程时,它不会终止该进程创建的任何子进程。终止进程不会为 WH_CBT 挂钩过程生成通知。. 这是我要问的理想行为。这适用于 win32 powershell 自动。但是对于 linux powershell Start-Job,它只是 powershell 上下文中的后台作业,因为它在 powershell 被杀死时被杀死。

例子:

➜  ~ powershell-preview -c "Start-Job { /bin/sleep 1000 }"

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
1      Job1            BackgroundJob   Running       True            localhost             /bin/sleep 1000

➜  ~ ps ux  | grep sleep
mvaidya   166986  0.0  0.0   9032   664 pts/11   S+   18:59   0:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --exclude-dir=.idea --exclude-dir=.tox sleep
4

1 回答 1

3

使用Start-Job或 PowerShell v6+ 的&后台运算符不是一个选项,因为终止作业也会终止从它启动的子进程,这些作业在 Windows 和类 Unix 平台上都是如此

但是,您可以通过cmdlet实现nohup类似行为:Start-Process


类 Unix平台上,您可以结合Start-Process使用nohup
以下示例启动一个后台 PowerShell 实例,即使您关闭启动终端,该实例仍保持活动状态;. 它每秒发出一个,并在当前目录nohup的文件中收集 stdout 和 stderr 输出,如果它已经存在,则附加到这样的文件:nohup.out

# Runs for 2 minutes and appends both stdout and stderr output to ./nohup.out
Start-Process nohup 'pwsh -nop -c "1..120 | % { write-host . -nonewline; sleep 1 }"'

警告:从 PowerShell 7.2 开始,通过SSH连接运行此命令仅在通过启动连接时才有效ssh,而不是通过 PowerShell 自己的基于 SSH 的远程 cmdlet,例如Invoke-Command[1]Enter-PSSession

例如 -假设用户在目标计算机上的默认 shell 是pwsh(PowerShell),可以使用以下命令;请注意,为了分配伪终端(pty),需要选项-tnohup,以便认为它的标准输出连接到终端,因此将其输出发送到文件.\nohup.out):

ssh -t <user>@<host> 'Start-Process nohup ''pwsh -nop -c \"1..120 | % { write-host . -nonewline; sleep 1 }\"'''

请注意,从 PowerShell 7.1 开始,需要补偿 PowerShell 仍然损坏的参数传递给外部程序的令人惊讶的需求,\"而不是仅仅需要 - 请参阅此答案"

相比之下,如果用户在目标计算机上的默认 shell 是POSIX 兼容的shell,例如bash,请使用以下命令(从 PowerShell 运行):

# IMPORTANT: If the target machine runs macOS rather than Linux, use the
#            `pwsh`'s *full path*, which is `/usr/local/bin/pwsh` by default.
ssh -t <user>@<host> 'nohup pwsh -nop -c ''1..120 | % { write-host . -nonewline; sleep 1 }'' & whoami >/dev/null'

whoami >/dev/null请注意在提交后台作业 ( ) 后使用虚拟命令 &,这似乎是确保nohup获得足够时间来实际启动其目标命令所必需的。


Windows上,Start-Process默认情况下在新的控制台窗口中创建一个独立的进程,您可以使用-WindowStyle Hidden在隐藏窗口中启动该进程,该隐藏窗口将独立于启动 shell 保持活动状态。

# Runs for 2 minutes and appends success output to ./nohup.out
Start-Process -WindowStyle Hidden pwsh '-nop -c "1..120 | % { Add-Content -nonewline nohup.out -Value .; sleep 1 }"'

警告:这不能按原样工作远程处理

  • 在远程会话中,Start-Process不能以这种方式在单独的(隐藏)窗口中启动进程,因此在退出远程会话时,启动的进程也会终止

  • 但是,您可以创建一个断开连接的会话,该会话在目标计算机上保持活动状态,直到它被明确删除(或直到目标计算机重新启动);或者,显式创建一个常规(已连接)会话并根据需要保持它 - 尽管如果调用计算机在任务完成之前重新启动,则任务再次终止(除非您先显式断开会话)。

一个例子,使用Invoke-Command's-InDisconnectedSession开关:

# Launch the command remotely, in a disconnected session, and
# return a session-information object:
$disconnSess = Invoke-Command -Computer <host> -InDisconnectedSession {
  Start-Process -WindowStyle Hidden pwsh '-nop -c "1..120 | % { Add-Content -nonewline nohup.out -Value .; sleep 1 }"'
}

# ... Let the command finish

# Remove the session again
Remove-PSSession $disconnSess

[1] 这些 cmdlet 不分配伪终端 (pty),缺少伪终端会导致nohup将其输出打印到 stdout 和 stderr 而不是 file .\nohup.out。此外,这种意外的直接打印输出可能会导致远程 PowerShell 会话崩溃

于 2020-11-06T02:23:44.883 回答