标准输出和输入问题

好——你说得对,之前那条命令有逻辑错误,会导致“新日志为空”。下面把问题点、原因和可直接拷贝运行的修正命令都给你,并说明为何这样改。


为什么日志会是空的(问题点)

  1. > rsync-push-20250716.log 2>&1 是把 stdout 和 stderr 都写到日志

  2. 但你接着写了 2> /dev/null,它会 覆盖 前面的 2>&1(后出现的重定向生效),把 stderr 丢掉

    • 如果你的任务只输出到 stderr(很多错误/诊断信息会走 stderr),那日志里就看不到任何内容 → “看起来像空文件”。

  3. 另外,把 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 &

posted on 2025-08-22 10:48  吃草的青蛙  阅读(9)  评论(0)    收藏  举报

导航