在 Bash 脚本编程和日常的系统操作中,我们常常会遇到需要长时间运行任务的情况。
而 nohup、& 和 disown 这三个命令在处理后台任务和确保任务持续运行方面发挥着重要作用。本文将详细介绍它们的区别和用法。
一. & 命令
1、用法
& 是一个非常基础且常用的命令,它的主要作用是将一个命令放入后台执行,使得当前终端可以继续执行其他命令,而不需要等待该命令执行完毕。其基本语法如下:
command &
这里的 command 可以是任何合法的 shell 命令。
例如,我们有一个需要较长时间执行的脚本 long_running_script.sh,可以使用如下命令将其放入后台执行:
#!/bin/bash
# 创建一个简单的长时间运行脚本示例
cat << eof> long_running_script.sh
#!/bin/bash
for i in {1..10}; do
echo "Iteration $i of long - running task"
sleep 1
done
EOF
chmod +x long_running_script.sh
./long_running_script.sh &
2、示例
#!/bin/bash
sleep 100 &
echo "The sleep command is running in the background."
上述命令会让 sleep 命令在后台休眠 100 秒,此时终端会立即返回一个任务编号和进程 ID,如下所示:
[1] 12345
The sleep command is running in the background.
其中 [1] 是任务编号,12345 是该任务对应的进程 ID。
3、特点
任务与终端关联:使用 & 启动的任务仍然与当前终端会话绑定。如果关闭终端,该任务也会随之终止。
输出处理:任务的标准输出和标准错误输出仍然会显示在终端上,除非进行了重定向。
二. nohup 命令
1、用法
nohup 命令的主要功能是让一个命令忽略 SIGHUP(挂起信号),即使终端关闭或者用户注销,命令也会继续在后台运行。其基本语法如下:
nohup command [arguments] &
通常会结合 & 一起使用,将命令放入后台执行。
例如,运行一个需要长时间运行的 Python 脚本:
bash
#!/bin/bash
# 创建一个简单的长时间运行 Python 脚本示例
cat << eof> long_running_script.py
import time
for i in range(10):
print(f"Iteration {i} of long - running Python task")
time.sleep(1)
EOF
nohup python long_running_script.py &
2、示例
#!/bin/bash
nohup sleep 1000 &
echo "The sleep command with nohup is running in the background."
执行该命令后,会生成一个 nohup.out 文件,用于存储命令的标准输出和标准错误输出。终端会显示类似如下信息:
[1] 12346
nohup: ignoring input and appending output to 'nohup.out'
The sleep command with nohup is running in the background.
3、特点
忽略挂起信号:nohup 会让命令忽略 SIGHUP 信号,确保在终端关闭后命令仍然可以继续运行。
输出重定向:如果没有指定输出文件,命令的输出会被追加到 nohup.out 文件中。可以通过重定向操作将输出指定到其他文件,例如:
#!/bin/bash
nohup python long_running_script.py > output.log 2>&1 &
echo "The Python script is running in the background, output redirected to output.log"
上述命令将标准输出和标准错误输出都重定向到 output.log 文件中。
三. disown 命令
1、用法
disown 命令用于从当前 shell 的作业列表中移除一个作业,使其不再受当前终端会话的控制。其基本语法如下:
disown [options] [job_spec]
job_spec 可以是任务编号(如 %1)或者进程 ID。例如,将任务编号为 1 的作业从作业列表中移除:
#!/bin/bash
sleep 200 &
job_id=$!
echo "The sleep command is running as job with ID: $job_id"
disown %1
jobs
2、示例
#!/bin/bash
# 启动一个后台任务
sleep 300 &
# 获取任务编号
job_num=$(jobs -l | grep "sleep 300" | awk '{print $1}' | tr -d '[]')
echo "The job number is $job_num"
# 使用 disown 移除作业
disown %$job_num
# 再次查看作业列表,确认作业已移除
jobs
在上述示例中,首先启动一个 sleep 后台任务,然后通过 jobs -l 命令获取该任务的编号,使用 disown 移除该作业,最后再次查看作业列表确认作业已被移除。
3、特点
脱离终端控制:disown 可以让已经在后台运行的任务脱离当前终端会话的控制,即使终端关闭,任务也不会终止。
与 & 结合使用:通常先使用 & 将命令放入后台执行,然后再使用 disown 让任务完全独立于终端。
四. 区别总结
1、关联关系
& 只是简单地将命令放入后台执行,任务仍然与终端会话紧密关联。
nohup 侧重于让命令忽略 SIGHUP 信号,确保在终端关闭后继续运行,通常结合 & 使用。
disown 用于将已经在后台运行的任务从当前终端的作业列表中移除,使其不再受终端控制。
2、输出处理
& 命令的输出默认显示在终端上,除非进行重定向。
nohup 会将输出默认存储在 nohup.out 文件中,也可以进行自定义重定向。
disown 本身不涉及输出处理,输出处理取决于任务启动时的设置。
3、使用场景
当只需要临时将命令放入后台,且不担心终端关闭影响任务时,可以使用 &。
当需要确保命令在终端关闭后仍然继续运行时,使用 nohup 结合 &。
当已经有任务在后台运行,需要让其完全脱离终端控制时,使用 disown。
综上所述,nohup、& 和 disown 这三个命令在处理后台任务和确保任务持续运行方面各有优势,合理使用它们可以提高我们的工作效率。