刚接手一台新服务器时,我习惯先看一眼别人留下的启动命令。大多数情况都是 nohup ./run.sh &,然后日志就静静躺在 nohup.out 里。这个文件平时不起眼,可一旦线上出问题,它就成了唯一的救命稻草。而"稻草"之所以能救命,前提是你得真正搞懂 nohup 的日志输出规则——默认写在哪、怎么改、怎么切分、怎么避免文件无限膨胀。这篇就来把这些事一次性说透。
nohup 本身并不复杂,但围绕它的日志设置,新手踩坑率极高。我在不同项目组都见过同款事故:要么日志里啥都没记录,要么 nohup.out 被撑到几十个 G 把磁盘打满,要么因为重定向顺序写错导致报错信息完全丢失。所以这篇不只是列命令,我会把每个写法背后的机制、适用场景、以及实际运维中的注意事项一并拆开讲,希望你能直接照搬,并且能举一反三。
1. nohup默认把日志写到哪:先搞清那行提示的真正含义
很多人在终端执行 nohup ./app & 后,会看到一行字:nohup: ignoring input and appending output to 'nohup.out'。这行提示不是随便写的,它其实透露了两个关键信息:输入被忽略,输出被追加到 nohup.out。
1.1 nohup的工作本质:不只是"后台运行"
nohup 的全称是 no hang up,核心作用是让进程忽略 SIGHUP 挂断信号。当我们关闭终端窗口或 SSH 会话断开时,终端会向前台进程组发送 SIGHUP 信号,默认行为是终止进程。nohup 让进程无视这个信号,于是即使你关掉终端,程序依然在后台继续跑。
注意一点:nohup 本身不是"后台运行"命令,它只是屏蔽了挂断信号。真正让进程进入后台的,是命令末尾的 &。所以标准写法是 nohup command &,两者配合,才能做到"关掉终端也不死、不占当前终端输入"。
1.2 为什么默认是nohup.out而不是别的文件
当 nohup 发现自己启动的命令其标准输出(stdout)和标准错误(stderr)仍然指向终端时,它会自动把这两个输出流重定向到一个文件,这个文件默认就叫 nohup.out,保存在当前工作目录下。如果当前目录没有写权限,则会尝试写到用户主目录下的 nohup.out。
这个设计的初衷是:既然你要在后台长时间跑程序,输出不能让终端一直刷屏,也不能因为终端关闭就丢失,所以统一落到一个文件里。但它也带来了第一个坑:nohup.out 默认是追加写入,不是覆盖写入。也就是说,你第二次启动任务,新的输出会接在旧内容后面,不会清空原来的文件。这个"追加"机制对排查问题是有利的——历史日志不会丢,但文件也会因此越积越大。
1.3 stdout和stderr:两条流向决定了日志完整性
在 Linux 里,每个进程默认有 3 个文件描述符:
- fd 0 标准输入(stdin),默认指向键盘
- fd 1 标准输出(stdout),默认指向终端屏幕
- fd 2 标准错误(stderr),默认也指向终端屏幕
程序正常的运行日志、结果输出走 stdout,而错误信息、异常堆栈走 stderr。多数情况下两者最终都打印到终端,肉眼看不出去别。但在日志重定向时,这两条流是独立的管道,你可以让它们进两个不同文件,也可以合并进同一个文件。
如果只做 nohup command &,nohup 发现 stdout 和 stderr 都是终端,就会把二者都指向 nohup.out。所以默认情况下报错信息也在里面,不会丢。但如果后面我们手动做了部分重定向,情况就复杂了,下面细讲。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 把日志重定向到指定文件:顺序写错会让报错日志跑偏
默认的 nohup.out 虽然能用,但生产环境里我们通常希望能把日志放到指定目录、指定文件名下,方便清理,也方便和其他进程的日志区分开。这就涉及到 shell 的重定向语法。
2.1 标准写法:nohup命令加三个重定向符号
要让一个程序在后台运行并把所有输出写入 /data/logs/app.log,最常用的完整写法是:
bash复制nohup java -jar app.jar > /data/logs/app.log 2>&1 &
拆开看:
> /data/logs/app.log:把标准输出重定向到文件(覆盖模式)2>&1:把标准错误重定向到标准输出当前
