Linux 后台运行

LinuxBeginner
立即练习

介绍

Linux 提供了强大的进程管理能力,允许用户在后台运行命令,同时继续在终端中工作。当处理耗时且不需要持续监控的任务时,这项功能至关重要。在本实验中,你将学习如何后台运行进程、检查其状态以及有效地管理它们。这些技能是所有 Linux 用户的基础,并在命令行环境中工作时提供更大的灵活性。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 90%。获得了学习者 98% 的好评率。

理解后台进程

在 Linux 中,进程可以运行在前台或后台。前台进程会占用你的终端直到完成,阻止你运行其他命令。而后台进程则可以在不阻塞终端的情况下运行,让你继续使用命令行。

首先,我们创建一个简单的脚本来模拟一个长时间运行的任务。这将帮助我们演示后台进程。

导航到项目目录:

cd ~/project

使用 nano 编辑器创建一个名为 long-task.sh 的文件:

nano long-task.sh

向文件中添加以下内容:

#!/bin/bash
## This script simulates a long-running task
echo "Starting long task..."
for i in {1..20}; do
  echo "Processing step $i..."
  sleep 5
done
echo "Long task completed."

Ctrl+O 然后按 Enter 保存文件,接着按 Ctrl+X 退出 nano。

通过更改脚本的权限使其可执行:

chmod +x long-task.sh

现在,在前台运行脚本:

./long-task.sh

你将看到脚本每隔 5 秒输出一个步骤。请注意,在此期间,你无法在终端中输入其他命令,因为该进程正在前台运行。

Ctrl+C 在脚本完成前终止它。

在后台运行进程

要在后台运行进程,只需在命令末尾加上一个与号 (&)。这会告诉 shell 在后台执行该命令。

让我们在后台运行我们的 long-task.sh 脚本:

cd ~/project
./long-task.sh &

你应该会看到类似以下的输出:

[1] 1234
Starting long task...
Processing step 1...

这里,[1] 是 shell 分配的作业号 (job number),而 1234 是进程 ID (PID)。作业号用于在 shell 中引用此后台进程,而 PID 则由操作系统用于标识进程。

请注意,在初始输出之后,你会重新获得命令提示符。现在你可以继续输入其他命令,同时脚本会在后台运行。

例如,尝试创建一个另一个文件:

echo "I can do other work while the script runs" > background-demo.txt
cat background-demo.txt

你会发现,你可以在终端中继续工作,同时偶尔看到后台脚本的输出。这对于运行耗时任务而不阻塞终端会话非常有用。

重要提示: 看到后台进程的输出出现在你的终端是完全正常的。当你使用 & 在后台运行进程时,进程在后台执行,但其输出流 (stdout 和 stderr) 仍然连接到你的终端。这意味着:

  • 进程在后台运行(你可以输入其他命令)
  • 进程会继续执行而不会阻塞你的终端
  • 输出仍然会显示在你的屏幕上(这可能会与你的其他命令混合)

这种行为是符合预期的,并表明后台进程正在积极运行并产生输出。

检查后台进程

Linux 提供了几个命令来检查哪些进程正在后台运行。最常用的两个是 jobsps

使用 jobs 命令

jobs 命令显示当前 shell 会话中所有后台作业的状态:

jobs

你应该会看到类似以下的输出:

[1]+  Running    ./long-task.sh &

+ 号表示这是当前默认的作业,这意味着如果你使用 fgbg 等命令而不指定作业号,它将是操作的对象。

使用 ps 命令

虽然 jobs 只显示当前 shell 启动的进程,但 ps 命令可以显示系统上运行的所有进程:

ps aux | grep long-task.sh

输出应该包含你的后台脚本的一行:

labex     1234  0.0  0.0   4508  1996 pts/0    S    12:34   0:00 /bin/bash ./long-task.sh

让我们创建另一个后台进程,以便我们可以看到多个作业:

cd ~/project
nano another-task.sh

添加以下内容:

#!/bin/bash
## This script simulates another task
echo "Starting another task..."
for i in {1..20}; do
  echo "Another task - step $i..."
  sleep 5
done
echo "Another task completed."

保存并退出 nano (Ctrl+O, Enter, Ctrl+X),然后使脚本可执行:

chmod +x another-task.sh

同样在后台运行此脚本:

./another-task.sh &

现在再次检查你的后台作业:

jobs

你应该会看到列出了两个作业:

[1]-  Running    ./long-task.sh &
[2]+  Running    ./another-task.sh &

管理后台进程

既然我们已经有了在后台运行的进程,让我们学习如何管理它们。Linux 提供了几个命令来控制后台进程:

将后台进程调到前台

fg 命令将后台进程调到前台。如果你有多个后台作业,你可以通过使用它们的作业号来指定是哪一个。

让我们将第一个作业调到前台:

fg %1

%1 指的是作业号 1。你将看到 long-task.sh 脚本的输出现在出现在你的终端中,并且在进程完成或你停止它之前,你的命令提示符将不可用。

要中断进程并返回命令提示符,请按 Ctrl+C

将前台进程放到后台

你也可以将前台进程放到后台。首先,使用 Ctrl+Z 挂起前台进程,然后使用 bg 命令在后台继续执行它。

启动一个新的前台进程:

cd ~/project
./long-task.sh

几秒钟后,按 Ctrl+Z 挂起进程。你会看到类似这样的消息:

[1]+  Stopped    ./long-task.sh

现在,在后台继续执行它:

bg

进程将在后台恢复运行,你将看到:

[1]+ ./long-task.sh &

你可以使用以下命令来验证它是否正在运行:

jobs

你应该会看到列出了两个作业:

[1]-  Running    ./long-task.sh &
[2]+  Running    ./another-task.sh &

终止后台进程

要终止后台进程,你可以使用 kill 命令并加上作业号或进程 ID:

kill %1

或者使用 PID(将 1234 替换为你 ps 输出中的实际 PID):

kill 1234

要验证进程是否已被终止:

jobs

你可能会看到一条消息表明作业已被终止:

[1]+  Terminated    ./long-task.sh

运行进程直至注销

有时你需要一个进程在退出终端后继续运行。nohup 命令允许你运行一个命令,即使在你退出 shell 后它也会继续运行。

让我们创建一个将长时间运行的脚本:

cd ~/project
nano persistent-task.sh

添加以下内容:

#!/bin/bash
## This script runs for a very long time
echo "Starting persistent task at $(date)" > persistent-output.log
for i in {1..100}; do
  echo "Iteration $i at $(date)" >> persistent-output.log
  sleep 10
done
echo "Persistent task completed at $(date)" >> persistent-output.log

保存并退出 nano,然后使脚本可执行:

chmod +x persistent-task.sh

现在,使用 nohup 运行它并将其放到后台:

nohup ./persistent-task.sh &

你将看到类似以下的输出:

[1] 5678
nohup: ignoring input and appending output to 'nohup.out'

这意味着进程正在后台运行,即使你退出登录也会继续运行。通常会输出到终端的内容被重定向到一个名为 nohup.out 的文件。

管理输出的技巧: 如果你不希望后台进程的输出出现在你的终端中并可能干扰你的工作,你可以将输出重定向到一个文件:

## 将输出重定向到一个特定文件
./long-task.sh > task-output.log 2>&1 &

## 或者重定向到 /dev/null 以完全丢弃输出
./long-task.sh > /dev/null 2>&1 &

2>&1 会重定向标准输出和错误输出。这样,后台进程将静默运行,而不会弄乱你的终端。

你可以检查进程是否正在运行:

ps aux | grep persistent-task.sh

你可以检查输出文件:

cat persistent-output.log

输出显示了持久化任务的开始时间和迭代次数。

disown 命令

另一种在退出登录后保持进程运行的方法是使用 disown 命令。首先,在后台运行一个进程:

cd ~/project
./persistent-task.sh &

然后使用 disown 将其从终端分离:

disown %1

现在即使你关闭终端,这个进程也会继续运行。

当你需要在远程服务器上运行任务,并且需要进程在断开连接后继续运行时,这些命令至关重要。

总结

在本实验中,你学习了管理后台进程的基本 Linux 技能。你已经练习了:

  1. 在前台和后台模式下创建和执行脚本
  2. 使用 & 运算符在后台运行进程
  3. 使用 jobsps 检查后台进程的状态
  4. 使用 fgbg 命令管理进程,将它们在前台和后台之间移动
  5. 使用 kill 命令终止后台进程
  6. 使用 nohupdisown 运行在退出登录后仍能继续的进程

这些技能对于在 Linux 环境中高效工作至关重要,尤其是在处理长时间运行的任务或在远程服务器上工作时。通过在后台运行进程,你可以通过同时执行多个任务而不阻塞你的终端会话来最大化你的生产力。