如何在终端中启动一个命令,使其不是终端的父进程?

25

让我们以一个命令 "example-command" 为例。

  1. 我打开终端
  2. 在终端中输入 example-command ,然后 example-command 被执行。
  3. 现在如果我关闭终端,example-command 也会被终止。
  4. 我现在尝试使用 "example-command &",但是行为相同。

如何执行一个命令,以便在关闭终端时该命令不会被终止?

8个回答

28

有两种方法,结果相同。

  1. 在启动程序时使用 nohup 命令。例如:nohup example-command。您可以将其后台运行并像平常一样工作,即使您退出也会继续运行。
  2. 此外,如 @alamar 所指出的(参见链接),如果您使用 bash 作为您的 shell,则可以使用 disown 命令。不幸的是,据我所知,disown 是特定于 bash 的;如果您使用另一个 shell,例如 tcsh,则可能会受到上面使用 nohup 形式的限制。

zsh 也支持 disown。 - alamar
哦,现在我记起来了,我过去使用过 nohup - Vikrant Chaudhary
从bash手册页面来看,似乎“-h”选项是必需的,以忽略SIGHUP -- “disown -h”。 - NVRAM
两种选项都可以解决杀死进程的问题,但父进程仍然是 shell。另一方面,setsid 会在新会话中启动命令。尝试运行 ps -o cmd= $(ps -o ppid= $(pidof example-command)) 来获取父进程名称。 - Ricardo Stuven

11

请先搜索类似的问题。

除了上面列出的方法,你可以尝试:

setsid command_name
例如:
setsid xclock

谢谢


3
请先搜索类似的问题。我已经搜索过了,先生。 - Vikrant Chaudhary

7
在Zsh(而不是bash)中,您可以:
example-command &; disown {pid}

或者只是
example-command &; disown

2
在符号&之后加分号是语法错误。在bash中,PID是可选的,而“-h”是必需的。因此,正确的写法应该是:“example-command & disown -h”,但这不会重定向stdin/stdout/stderr。 - NVRAM
在zsh中,"ls &; disown" 对我来说完全没问题。如果bash不支持这两个(&后面的;或没有参数的disown),那么:别告诉我你不知道它很糟糕。 - alamar
我同意@NVRAM的观点。我更新了答案,说明它适用于Zsh但不适用于Bash。 - Elijah Lynn

5
你也可以考虑使用screen命令来完成这个任务。

或者它的现代替代品 tmux - mic_e

1

disown是bash内置命令。您可以为您的命令创建一个包装器shell脚本,例如

#!/bin/bash
$1 &
P=`which $1`
disown `pidof ${P}`

这不是最健壮的脚本(绝非如此),但可能有助于您开始。例如:

$./launch_script.sh myProgram

如果您正在编辑程序源代码,也可以在其中执行此操作。


你的示例没有处理参数(使用“$@”)。您可以使用“$!”获取上一个后台作业的PID。但是,PID不是必需的。您应该忽略SIGHUP,因此请使用“nohup”或“disown -h”。 - NVRAM
谢谢NVRAM,已经有一段时间没有做过任何shell脚本了 :) - Aiden Bell

1

nohup 示例命令


1

我喜欢这个,但很少使用它。为了简化,只需使用“现在”(无需计算日期/时间)。 - NVRAM

-2

运行:example-command

按下:Control-Z

运行:bg


这与运行 example-command & 相同,但并没有起作用。example-command 仍然作为子进程运行。 - Christian Mann
1
我建议你使用screen。 screen vi Control+a d [将分离] screen -r [将重新连接] 你可以关闭终端,几天后再用该用户进行screen -r操作。 你可以拥有多个screen会话。 - Eduardo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接