在Shell脚本中结合nohup实现免回车并将stdout重定向至PID 1
解决nohup后台运行Python脚本并将输出定向到PID 1 stdout的问题
我来帮你梳理下问题所在,以及对应的解决方案:
首先,你遇到的核心矛盾是:既要让nohup完全后台运行(无提示、无需回车),又要把Python脚本的标准输出(也就是你通过logging配置打到stdout的日志)转发到PID 1的标准输出。
为什么你的尝试没生效?
你之前的命令nohup python tester.py > /proc/1/fd/1 2> /dev/null &其实已经接近正确,但可能忽略了标准输入的处理——nohup默认会把stdin重定向到/dev/null,但如果你的shell脚本是从终端启动的,stdin仍关联终端,可能会导致一些隐性的输出提示(或者Python进程可能意外读取stdin)。另外,有时候/proc/1/fd/1的权限或存在性也会影响,但更可能是重定向的完整性问题。
正确的命令写法
试试这个完整的命令,它会同时满足你的两个需求:
nohup python tester.py > /proc/1/fd/1 2> /dev/null < /dev/null &
让我拆解下每个部分的作用:
> /proc/1/fd/1:将Python脚本的stdout(也就是你的日志输出)直接定向到PID 1的标准输出2> /dev/null:将所有stderr(包括nohup本身的提示信息)丢弃,避免出现需要回车的提示< /dev/null:显式将stdin重定向到/dev/null,彻底切断进程与终端的输入关联,确保nohup不会产生任何终端相关的提示&:将进程放到后台运行
验证你的Python日志配置
另外,确认你的logging配置确实在往stdout输出:
你当前的代码是正确的,但可以再检查下日志级别是否正确设置,确保日志内容确实会被输出到StreamHandler:
import logging import sys formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') importer_logger = logging.getLogger('importer') importer_logger.setLevel(logging.INFO) # 确保级别足够低,能输出你的日志 stream_config = logging.StreamHandler(sys.stdout) stream_config.setFormatter(formatter) importer_logger.addHandler(stream_config)
替代方案:不用nohup,用disown
如果你不想依赖nohup,也可以用disown来让进程脱离终端,避免SIGHUP信号,同时实现相同的输出定向:
python tester.py > /proc/1/fd/1 2> /dev/null < /dev/null & disown
这个命令的效果和nohup类似,但不会生成nohup.out文件,也没有任何提示信息。
注意事项
- 确保
/proc/1/fd/1是存在且可写的:在容器环境中,PID 1通常是你的应用或init进程,这个路径是有效的;在宿主机上,如果PID 1是systemd,它的stdout可能指向journald,你的输出会被日志系统捕获。 - 如果
/proc/1/fd/1失效(比如PID 1重启),你的Python进程的输出会丢失,这是重定向到动态fd的固有特性。
内容的提问来源于stack exchange,提问作者Avión
相关产品推荐
相关产品推荐

