标准输出和输入问题
好——你说得对,之前那条命令有逻辑错误,会导致“新日志为空”。下面把问题点、原因和可直接拷贝运行的修正命令都给你,并说明为何这样改。
为什么日志会是空的(问题点)
-
> rsync-push-20250716.log 2>&1是把 stdout 和 stderr 都写到日志。 -
但你接着写了
2> /dev/null,它会 覆盖 前面的2>&1(后出现的重定向生效),把 stderr 丢掉。-
如果你的任务只输出到 stderr(很多错误/诊断信息会走 stderr),那日志里就看不到任何内容 → “看起来像空文件”。
-
-
另外,把
nohup放在cat前面:nohup cat ... | xargs ...只对cat生效,并不会保护后面由xargs启动的子进程(它们仍可能收到 SIGHUP)。这会在会话结束时导致任务被杀掉,进一步造成日志无内容或任务中断。
最终推荐(保证日志不为空,捕获 stdout/stderr,整个 pipeline 不会因 SIGHUP 死掉)
方案 A — 使用 nohup 包裹整个 pipeline(常用)
nohup sh -c 'cat rsync-push.sh | xargs -I {} -P 5 sh -c "{}"' > rsync-push-20250716.log 2>&1 < /dev/null &
说明
-
sh -c '...'把整个 pipeline 包成一个命令,nohup会保护管道内所有子进程不被 SIGHUP 杀死。 -
> ... 2>&1把 stdout/stderr 都写进日志(不再丢弃 stderr)。 -
< /dev/null避免任何命令等待输入。 -
这样日志会包含所有输出(包括
nohup的启动提示,如果有的话)。
方案 B — 不想在日志里看到 nohup: 提示,改用 setsid
setsid sh -c 'cat rsync-push.sh | xargs -I {} -P 5 sh -c "{}"' > rsync-push-20250716.log 2>&1 < /dev/null &
说明
-
setsid启动一个新的会话,不会像nohup那样打印 “nohup: ignoring input …” 的提示。 -
同样将 stdout/stderr 全写入日志,且保护整个 pipeline。
方案 C — 更简洁(避免 cat,用 xargs -a)
nohup sh -c 'xargs -a rsync-push.sh -I {} -P 5 sh -c "{}"' > rsync-push-20250716.log 2>&1 < /dev/null &
或用 setsid 替代 nohup,同上。
若你确实想 删除日志中可能存在的第一行(nohup 提示)
(先把输出都写到日志,再把提示删掉)
# 启动(示例使用 nohup)
nohup sh -c 'cat rsync-push.sh | xargs -I {} -P 5 sh -c "{}"' > rsync-push-20250716.log 2>&1 < /dev/null &
# 启动后(如果第一行为 nohup 提示,删除它)
sed -i '1{/^nohup: /d}' rsync-push-20250716.log
启动后检查(确保日志有内容)
-
查看进程是否仍在运行:
pgrep -a xargs
ps aux | grep '[x]args'
-
快速查看日志前几行 / 末尾:
head -n 50 rsync-push-20250716.log
tail -n 200 rsync-push-20250716.log
小结(推荐)
-
最稳妥:用
nohup sh -c '...' >log 2>&1 < /dev/null &或者 更优雅的setsid sh -c '...' >log 2>&1 < /dev/null &。 -
千万别同时写
> logfile 2>&1又写2>/dev/null(会把 stderr 丢掉,造成“日志为空”或缺失错误信息)。
需要我把其中一个命令替换成你当前生产环境的精确版本(比如并发数、rsync 行如何写),或给出一个可测试的最小 demo(验证日志是否会写入)?
nohup sh -c 'rm -rf wangzeyu' > /dev/null 2>&1 < /dev/null &
浙公网安备 33010602011771号