nohup命令

nohup命令 #

nohup命令(no hang up)用于运行命令,使其忽略挂起(SIGHUP)信号。这使得命令可以在用户注销后继续运行,常用于在后台运行长时间执行的任务。

语法 #

nohup 命令 [参数...] [&]

常用选项 #

nohup命令本身没有太多选项,但通常与其他命令和操作符结合使用:

符号 描述
& 将命令放在后台运行
> 文件 将标准输出重定向到文件
2> 文件 将标准错误重定向到文件
2>&1 将标准错误重定向到标准输出
--help 显示帮助信息
--version 显示版本信息

工作原理 #

当用户注销(登出)系统时,系统会向该用户的所有进程发送SIGHUP(挂起)信号。默认情况下,进程接收到SIGHUP信号后会终止。nohup命令使进程忽略SIGHUP信号,从而允许进程在用户注销后继续运行。

默认情况下,nohup命令会将输出重定向到nohup.out文件,除非标准输出被重定向到其他位置。

常见用法 #

1. 在后台运行命令并忽略挂起信号 #

nohup command &

这会在后台运行命令,并将输出保存到nohup.out文件。

2. 将输出重定向到特定文件 #

nohup command > output.log 2>&1 &

这会在后台运行命令,将标准输出和标准错误都重定向到output.log文件。

3. 将标准输出和标准错误分别重定向 #

nohup command > output.log 2> error.log &

4. 丢弃所有输出 #

nohup command > /dev/null 2>&1 &

5. 运行脚本并忽略挂起信号 #

nohup ./script.sh &

6. 查看nohup进程的PID #

nohup command &
echo $!

$!变量包含最近一个后台进程的PID。

7. 使用特定的nice值运行命令 #

nohup nice -n 19 command &

这会以最低优先级运行命令。

与其他命令结合使用 #

1. 结合time命令测量长时间运行的命令 #

nohup time long_running_command > output.log 2>&1 &

2. 在特定时间运行命令 #

nohup bash -c "sleep 3600 && command" &

这会在1小时后运行命令。

3. 使用at命令在特定时间运行 #

echo "nohup command > output.log 2>&1" | at 2am

4. 使用screen或tmux代替nohup #

screen -dm bash -c "command; echo 'Command completed'"

tmux new-session -d "command; echo 'Command completed'"

实用示例 #

1. 运行长时间的数据处理任务 #

nohup python3 data_processing.py > processing.log 2>&1 &

2. 在后台运行服务器 #

nohup ./server --port 8080 > server.log 2>&1 &

3. 运行备份脚本 #

nohup bash backup.sh > backup.log 2>&1 &

4. 运行数据库导出 #

nohup mysqldump -u user -p database > dump.sql 2> dump.err &

5. 下载大文件 #

nohup wget -c https://example.com/large_file.iso &

6. 运行耗时的编译任务 #

nohup make -j4 > build.log 2>&1 &

7. 运行多个命令 #

nohup bash -c "command1 && command2 && command3" > output.log 2>&1 &

查看和管理nohup进程 #

1. 查看nohup进程 #

ps -ef | grep nohup

jobs -l

2. 终止nohup进程 #

kill PID

3. 查看nohup.out文件 #

tail -f nohup.out

4. 检查进程是否仍在运行 #

ps -p PID

替代方案 #

除了nohup命令外,还有其他方法可以使进程在用户注销后继续运行:

  1. screen命令:创建可分离的终端会话

    screen -S session_name
    # 运行命令
    # 按Ctrl+A, 然后按D分离会话
    # 使用screen -r session_name重新连接
    
  2. tmux命令:终端复用器

    tmux new -s session_name
    # 运行命令
    # 按Ctrl+B, 然后按D分离会话
    # 使用tmux attach -t session_name重新连接
    
  3. disown命令:从当前shell的作业表中移除作业

    command &
    disown %1
    
  4. systemd服务:创建用户级服务

    # 创建~/.config/systemd/user/myservice.service文件
    systemctl --user start myservice
    

注意事项 #

  1. nohup命令不会自动将进程放在后台运行,需要使用&操作符。

  2. 如果不重定向输出,nohup会将输出保存到当前目录下的nohup.out文件。如果当前目录不可写,则保存到$HOME/nohup.out

  3. nohup命令只能忽略SIGHUP信号,不能忽略其他信号(如SIGTERM或SIGKILL)。

  4. 使用nohup运行的进程仍然与终端的标准输入关联,除非明确重定向。

  5. 在某些系统上,即使不使用nohup,通过&放在后台的进程也可能不会收到SIGHUP信号。

提示 #

  • 总是重定向nohup命令的输出,以便稍后查看结果或错误
  • 记录nohup进程的PID,以便稍后可以检查其状态或终止它
  • 对于更复杂的需求,考虑使用screentmux等工具
  • 使用nohup运行的进程仍然会在系统重启后终止,如果需要在系统重启后自动启动,应该使用系统的初始化系统(如systemd)
  • 在脚本中使用nohup时,考虑使用完整路径指定命令和输出文件
  • 对于需要交互的命令,nohup可能不是最佳选择,因为它会与终端分离
  • 使用nohup运行的进程仍然会在父进程终止时收到SIGHUP信号,除非它已经成为孤儿进程并被init进程收养