让Linux终端中执行的程序在后台运行 从前台变到后台

本文详细介绍了在Linux环境下如何通过&符号将命令放入后台运行,使用nohup命令忽略终端退出信号,以及如何使用setsid命令将进程与当前shell分离,确保进程在退出shell时仍能继续运行。此外,文章还介绍了如何使用disown命令解除对后台进程的控制,以及在子shell中执行命令的方法来实现类似效果。

在Linux中,如果要让进程在后台运行,一般情况下,我们在命令后面加上&即可,实际上,这样是将命令放入到一个作业队列中了:

  $ ./test.sh &

  [1] 17208

  $ jobs -l

  [1]+ 17208 Running ./test.sh &

  对于已经在前台执行的命令,也可以重新放到后台执行,首先按ctrl+z暂停已经运行的进程,然后使用bg命令将停止的作业放到后台运行:

  $ ./test.sh

  [1]+ Stopped ./test.sh

  $ bg %1

  [1]+ ./test.sh &

  $ jobs -l

  [1]+ 22794 Running ./test.sh &

  

但是如上方到后台执行的进程,其父进程还是当前终端shell的进程,而一旦父进程退出,则会发送hangup信号给所有子进程,子进程收到hangup以后也会退出。如果我们要在退出shell的时候继续运行进程,则需要使用nohup忽略hangup信号,或者 setsid将将父进程设为init进程(进程号为1)

  $ echo $$

  21734

  $ nohup ./test.sh &

  [1] 29016

  $ ps -ef | grep test

  515 29710 21734 0 11:47 pts/12 00:00:00 /bin/sh ./test.sh

  515 29713 21734 0 11:47 pts/12 00:00:00 grep test

 

  $ setsid ./test.sh &

  [1] 409

  $ ps -ef | grep test

  515 410 1 0 11:49 ? 00:00:00 /bin/sh ./test.sh

  515 413 21734 0 11:49 pts/12 00:00:00 grep test

  上面的试验演示了使用nohup/setsid加上&使进程在后台运行,同时不受当前shell退出的影响。那么对于已经在后台运行的进程,该怎么办呢?可以使用disown命令:

  $ ./test.sh &

  [1] 2539

  $ jobs -l

  [1]+ 2539 Running ./test.sh &

  $ disown -h %1

  $ ps -ef | grep test

  515 410 1 0 11:49 ? 00:00:00 /bin/sh ./test.sh

  515 2542 21734 0 11:52 pts/12 00:00:00 grep test

  另外还有一种方法,即使将进程在一个subshell中执行,其实这和setsid异曲同工。方法很简单,将命令用括号() 括起来即可:

  $ (./test.sh &)

  $ ps -ef | grep test

  515 410 1 0 11:49 ? 00:00:00 /bin/sh ./test.sh

  515 12483 21734 0 11:59 pts/12 00:00:00 grep test

 原文出自【比特网】,转载请保留原文链接:http://soft.chinabyte.com/os/379/12244379.shtml

 

 

 

setsid命令

  linux常用的命令

  setsid命令的一般格式:

  setsid();

  说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。

  pid_t pid = fork();

  if (pid == 0) {

  ...

  int result = execl(path, "adb", "fork-server", "server", NULL);

  } else {

  // run a program in a new session

  setsid();//之前parent和child运行在同一个session里,而且parent是session头,所以,

  //所以作为session头的parent如果exit结束执行的话,那么会话session组中的所有进程将都被杀死,

  //所以执行setsid()之后,parent将重新获得一个新的会话session组id,child将仍持有原有的会话session组,

  //这时parent退出之后,将不会影响到child了[luther.gliethttp].

  }

  setsid()的返回值:

  成功:调用进程的会话ID;

  失败:-1;



http://blog.sina.com.cn/s/blog_605f5b4f0100x2bq.html

http://blog.chinaunix.net/uid-24517549-id-4030121.html

<think>首先,用户的问题是:“在Linux系统中让后台程序的标准输出显示在终端上的方法”。用户提供了多个引用,我需要参考这些引用来回答问题。 引用总结如下: - [^1]: 关于改变运行程序的stdout,特别是当程序后台拉起时,stdout被重定向到/dev/null的情况。 - [^2]: 解释stdin, stdout, stderr默认与终端相关联,但可以被重定向。 - [^3]: 详细描述标准输出的默认行为、缓冲区机制,以及如何通过重定向改变输出位置。 - [^4]: 提到使用screen命令来维终端会话,即使SSH断开也能保程序运行。 - [^5]: 讨论Java程序Linux后台运行时的输出重定向。 用户的问题核心是:如何让后台程序的stdout显示在终端上。背景是程序后台拉起,stdout被重定向到/dev/null,用户无法获取错误信息,且不能杀死程序以免破坏现场。 从系统级指令: - 所有行内数学表达式用$...$,但这个问题不涉及数学表达式,所以可能不需要。 - 独立公式用$$...$$,同样不相关。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 引用的段落末尾添加引用标识如[^1]。 回答结构: - 帮助用户逐步解决问题。 - 尽量真实可靠。 关键方法总结自引用: 1. **避免后台程序stdout被重定向**:如果程序是由后台拉起导致stdout被重定向,可能需要修改拉起脚本或命令。 2. **使用重定向**:在启动程序时,重定向stdout到终端。引用[^3]提到可以使用重定向操作符,如`>`或`>&`。 - 例如:`./program > /dev/tty` 或类似方式,但/dev/tty代表当前终端。 3. **使用screen或tmux**:引用[^4]提到screen可以创建一个虚拟终端,即使SSH断开,程序也能继续运行,且输出可以被查看。 - 具体来说,screen允许用户附加到会话查看输出。 4. **临时修改运行程序的stdout**:用户提到不能杀死程序,所以需要在不重启的情况下改变stdout。 - 从引用[^1]和搜索关键词,可能涉及使用工具如gdb或其他方法。 - 常见方法:使用`strace`或`gdb`来修改文件描述符。 深入方法: - 对于已运行后台程序,改变其stdout的方法: - **使用gdb**:附加到进程,调用dup2系统调用来redirect stdout。 - 示例:`gdb -p PID`,然后在gdb中执行命令如`call dup2(open("/dev/tty", O_WRONLY), 1)`。这需要编程知识。 - **使用reptyr**:一个工具可以重新附加终端到一个运行中的进程。 - 对于启动时的重定向: - 在命令行中,使用`&`后台运行,但重定向stdout到终端,如`./program > /dev/pts/0 &`,其中/dev/pts/0是当前终端。 - 但用户提到程序后台拉起,所以可能需要修改启动脚本。 用户场景:程序后台拉起,stdout重定向到/dev/null,不能重启程序。 因此,重点应放在如何在不重启的情况下修改运行程序的stdout。 步骤回答: 1. 理解当前情况。 2. 介绍临时修改方法。 3. 预防未来问题的方法。 生成相关问题:在回答末尾添加。 回答结构: - 先用中文清晰解释。 - 引用相关段落。 - 结束时生成问题。 最终回答大纲: 1. 介绍问题背景。 2. 方法一:使用gdb修改运行中进程的stdout。 - 详细步骤。 3. 方法二:使用reptyr或其他工具。 4. 方法三:预防措施,如使用screen。 5. 总结。 6. 生成相关问题。 确保语言专业、友好。 </think>在Linux系统中,让后台程序的标准输出(stdout)显示在终端上,是一个常见的需求,尤其当程序后台进程(如守护进程或脚本)拉起,且stdout被重定向到其他位置(如`/dev/null`)时。您提到不能杀死程序以保护现场,因此我会重点介绍**不重启程序**的临时修改方法。以下是几种可靠的方法,从简单到复杂逐步说明。这些方法基于您提供的引用(特别是[^1]和[^3]),并结合Linux系统特性。 ### 1. **使用`/dev/tty`重定向(适用于启动时控制)** 如果程序是由您手动启动的(或可修改启动命令),在后台运行时直接将stdout重定向到当前终端设备文件(`/dev/tty`)。`/dev/tty`代表当前控制终端,确保输出显示在您的终端窗口。 - **命令示例**: ```bash ./your_program > /dev/tty & ``` - 解释:`> /dev/tty` 将stdout重定向到当前终端,`&`将程序放入后台运行。 - **优点**:简单易用,不需要额外工具。 - **缺点**:仅适用于您能控制启动命令的场景。如果程序已由后台进程拉起(如systemd或init脚本),此方法不适用[^3]。 - **注意**:如果终端关闭,输出会丢失。使用`screen`或`tmux`可以解决这个问题(见方法3)。 ### 2. **修改运行程序的stdout(不重启程序)** 针对程序运行且不能重启的情况,您需要附加到进程并修改其文件描述符(File Descriptor)。标准输出对应文件描述符`1`。以下是两种常用方法: - **方法A:使用`gdb`(GNU Debugger)** `gdb`可以附加到运行中的进程,调用系统函数(如`dup2`)强制重定向stdout。 - **步骤**: 1. 查找程序进程ID(PID): ```bash ps aux | grep your_program_name ``` 2. 使用`gdb`附加到进程(替换`PID`为实际值): ```bash gdb -p PID ``` 3. 在gdb命令行中执行: ```gdb (gdb) call dup2(open("/dev/tty", 1), 1) (gdb) detach (gdb) quit ``` - 解释:`open("/dev/tty", 1)`以写入模式打开当前终端,`dup2`将stdout(描述符1)重定向到该终端。`detach`退出时不影响进程运行。 - **优点**:安全、可靠,且不中断程序执行。 - **缺点**:需要安装gdb(`sudo apt install gdb`),并确保进程未受ptrace保护(如某些容器环境)。 - **参考**:此方法基于Linux文件描述符机制,允许动态重定向stdout[^1]。 - **方法B:使用`reptyr`工具** `reptyr`("re-pty-er")专门用于将运行中的进程重新附加到新终端。 - **步骤**: 1. 安装`reptyr`: ```bash sudo apt install reptyr # Debian/Ubuntu ``` 2. 在当前终端启动一个`screen`或`tmux`会话(以创建一个稳定的终端环境): ```bash screen -S output_session # 创建一个名为output_session的screen会话 ``` 3. 在screen会话中,附加到目标进程: ```bash reptyr PID ``` - 替换`PID`为程序的实际进程ID。 4. 程序输出会自动显示在screen会话中。您可以通过`screen -r output_session`查看。 - **优点**:专为终端重定向设计,兼容性好。 - **缺点**:需要额外安装工具,且在SSH断开后需通过screen恢复会话。 - **参考**:类似`screen`的虚拟终端机制,能维后台输出[^4]。 ### 3. **使用screen或tmux维终端会话(预防性措施)** 如果程序经常需要后台运行,使用`screen`或`tmux`创建虚拟终端会话,从启动阶段就避免输出丢失。输出始终显示在会话中,即使SSH断开也能恢复。 - **步骤**: 1. 安装screen(若未安装): ```bash sudo apt install screen ``` 2. 启动新screen会话并运行程序: ```bash screen -S my_session # 创建会话 ./your_program # 在前台运行程序 ``` 3. 按`Ctrl+A D`分离会话,程序继续在后台运行。 4. 重新登录后附加会话查看输出: ```bash screen -r my_session ``` - **优点**:输出永久可见,适合长期后台任务。 - **缺点**:需要事前设置,不能在程序运行后动态附加。 - **参考**:screen充当虚拟终端,让程序认为终端始终连接,避免输出重定向[^4]。 ### 总结与建议 - **推荐方法**: - 如果不能修改程序(已运行):优先使用`gdb`或`reptyr`动态修改stdout。 - 如果可以控制启动:使用`> /dev/tty &`或`screen`从源头保证输出。 - **注意事项**: - 输出缓冲区问题:如果程序使用缓冲输出(如未换行`\n`),输出可能延迟显示。可通过设置环境变量`PYTHONUNBUFFERED=1`(Python程序)或`stdbuf -oL ./program`(通用)禁用缓冲[^3]。 - 安全风险:修改运行中进程需权限,确保您有`ptrace`能力(检查`/proc/sys/kernel/yama/ptrace_scope`)。 - 如果您无法操作生产环境,考虑联系系统管理员。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值