MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Bash中的进程管理与作业控制

2023-01-276.7k 阅读

进程的基本概念

在深入探讨 Bash 中的进程管理与作业控制之前,让我们先回顾一下进程的基本概念。进程是程序在计算机中的一次执行实例。当你运行一个程序时,操作系统会为该程序分配资源,包括内存、CPU 时间等,并创建一个进程来执行该程序。每个进程都有一个唯一的标识符,称为进程 ID(PID),这是操作系统用来跟踪和管理进程的关键标识。

例如,在 Linux 系统中,你可以通过 ps 命令查看当前系统中的进程。以下是一个简单的 ps 命令示例:

ps aux

这个命令会列出所有用户的进程信息,包括进程的所有者(USER)、CPU 使用率(%CPU)、内存使用率(%MEM)、进程 ID(PID)等详细信息。

Bash 中的进程启动

在 Bash 中启动一个进程非常简单。你只需在命令行中输入要执行的命令即可。例如,要启动 ls 命令来列出当前目录下的文件和目录,你可以这样做:

ls

当你输入这个命令并按下回车键时,Bash 会创建一个新的进程来执行 ls 程序。这个新进程会读取当前目录的内容,并将结果输出到终端。

如果你想要在后台启动一个进程,可以在命令后面加上 & 符号。例如,假设你有一个名为 long_running_script.sh 的脚本,它会执行一些耗时较长的操作,你可以这样在后台启动它:

./long_running_script.sh &

这样,脚本会在后台运行,你可以继续在终端执行其他命令,而不需要等待该脚本执行完毕。

前台与后台进程

  1. 前台进程 前台进程是指在当前终端中运行,并占用终端输入输出的进程。当你启动一个前台进程时,在该进程执行完毕之前,你无法在同一终端中执行其他命令,除非该进程允许你进行交互操作。例如,当你运行一个文本编辑器,如 nano,它就是一个前台进程。你需要在 nano 中完成编辑并退出后,才能在终端中执行其他命令。
nano myfile.txt

nano 运行期间,终端的控制权被 nano 占用。

  1. 后台进程 后台进程则是在终端的后台运行,不占用终端的输入输出。你可以在后台启动进程后,继续在同一终端执行其他命令。如前文所述,在命令后加上 & 符号即可将进程置于后台运行。例如,启动一个长时间运行的备份脚本:
./backup_script.sh &

此时,你可以立即在终端中执行其他命令,而备份脚本会在后台默默运行。

作业控制

  1. 作业的概念 在 Bash 中,作业是指一个或多个相关进程的集合。通常,当你在终端中启动一个命令,无论是前台还是后台,它都会被视为一个作业。例如,当你启动 ls 命令,这就是一个简单的作业;当你启动一个包含多个命令的管道,如 ls | grep "txt",这整个管道也被视为一个作业。

  2. 查看作业列表 你可以使用 jobs 命令来查看当前终端中的作业列表。例如,假设你在后台启动了两个进程:

sleep 60 &
sleep 120 &

然后,你可以使用 jobs 命令查看作业列表:

jobs

输出可能如下:

[1]  + running    sleep 60
[2]  - running    sleep 120

这里,[1][2] 是作业编号,+ 表示该作业是最近放入后台的作业,- 表示次近放入后台的作业。

  1. 将后台作业切换到前台 你可以使用 fg 命令将后台作业切换到前台运行。fg 命令后可以跟上作业编号。例如,要将作业 [1] 切换到前台,你可以这样做:
fg %1

这里的 %1 表示作业编号为 1 的作业。作业编号前的 % 符号是可选的,但加上它可以使命令更加明确。

  1. 将前台作业切换到后台 如果一个前台作业正在运行,你可以通过按下 Ctrl + Z 组合键将其暂停,并放入后台。例如,假设你正在运行 nano myfile.txt,按下 Ctrl + Z 后,nano 会暂停运行,并被放入后台。此时,你可以使用 jobs 命令查看作业列表,会看到 nano 作业处于暂停状态。然后,你可以使用 bg 命令将暂停的作业在后台继续运行。例如,要继续运行刚才暂停的 nano 作业:
bg %1

这里假设 nano 作业的编号为 1

进程的终止

  1. 使用 kill 命令终止进程 kill 命令是用于终止进程的常用工具。它通过向进程发送信号来通知进程终止。你可以使用进程 ID(PID)来指定要终止的进程。例如,假设你知道某个进程的 PID 为 1234,你可以使用以下命令终止该进程:
kill 1234

默认情况下,kill 命令会发送 SIGTERM 信号,这是一个请求进程正常终止的信号。大多数进程在收到 SIGTERM 信号后,会尝试清理资源并优雅地退出。

  1. 发送不同的信号 kill 命令可以发送多种不同的信号。例如,如果你想要强制终止一个进程,而不管它是否愿意正常退出,可以发送 SIGKILL 信号。SIGKILL 信号不能被进程捕获或忽略,会立即终止进程。要发送 SIGKILL 信号,可以使用以下命令:
kill -9 1234

这里的 -9 表示 SIGKILL 信号。不过,使用 SIGKILL 信号应该是最后的手段,因为它不会给进程留下清理资源的机会,可能会导致数据丢失或系统状态不一致。

  1. 通过作业编号终止作业 你也可以通过作业编号来终止作业。例如,要终止作业 [1],你可以使用以下命令:
kill %1

这会向作业 [1] 中的所有进程发送默认的 SIGTERM 信号。

进程间通信

  1. 管道(Pipe) 管道是一种简单而强大的进程间通信机制。它允许你将一个进程的输出作为另一个进程的输入。在 Bash 中,使用 | 符号来创建管道。例如,假设你想要列出当前目录下的所有文件,并筛选出文件名中包含 txt 的文件,你可以使用以下命令:
ls | grep "txt"

这里,ls 命令的输出通过管道传递给 grep 命令作为输入,grep 命令则在输入中查找包含 txt 的行并输出。

  1. 重定向 重定向也是一种进程间通信的方式,它允许你改变进程的输入输出流向。常见的重定向操作符有 >(输出重定向)、>>(追加输出重定向)、<(输入重定向)。

例如,要将 ls 命令的输出保存到一个文件中,可以使用输出重定向:

ls > file_list.txt

这会将 ls 的输出写入 file_list.txt 文件,如果文件已存在,会覆盖原有内容。如果要追加输出到文件,可以使用 >>

echo "This is a new line" >> file_list.txt

输入重定向则可以让进程从文件中读取输入。例如,假设你有一个名为 input.txt 的文件,里面包含一些文本,你可以使用 cat 命令通过输入重定向读取该文件内容:

cat < input.txt

守护进程

  1. 守护进程的概念 守护进程是一种在后台运行,不与任何终端关联的进程。它通常在系统启动时自动启动,并持续运行,为系统提供各种服务,如网络服务、文件服务等。守护进程独立于用户登录会话,即使所有用户都注销,守护进程仍然可以继续运行。

  2. 创建守护进程 在 Bash 中创建守护进程相对复杂一些。一种常见的方法是通过 nohup 命令。nohup 命令可以使进程忽略 SIGHUP 信号(当用户注销时,终端会向所有相关进程发送 SIGHUP 信号),从而使进程在用户注销后仍能继续运行。例如,假设你有一个名为 my_daemon.sh 的脚本,你可以使用以下命令将其作为守护进程运行:

nohup./my_daemon.sh &

这样,my_daemon.sh 脚本会在后台运行,并且不会因为用户注销而终止。nohup 命令默认会将进程的标准输出和标准错误输出重定向到 nohup.out 文件中。

进程管理的高级技巧

  1. 使用 setsid 命令创建新会话 setsid 命令可以创建一个新的会话,并在该会话中启动一个进程。这对于创建守护进程非常有用,因为它可以使进程脱离当前终端会话的控制。例如,假设你想要创建一个新的会话并在其中运行 my_script.sh 脚本:
setsid./my_script.sh &

这样,my_script.sh 脚本会在一个新的会话中运行,与当前终端会话完全分离。

  1. 进程优先级调整 在 Linux 系统中,你可以通过 nice 命令来调整进程的优先级。nice 值的范围从 -20(最高优先级)到 19(最低优先级),默认值为 0。例如,如果你想要以较低的优先级运行一个进程,可以使用以下命令:
nice -n 10./resource_intensive_script.sh &

这里,-n 10 表示将进程的 nice 值设置为 10,即较低的优先级。这样,该进程在竞争系统资源时会相对其他进程更“谦让”。

  1. 实时监控进程资源使用情况 top 命令是一个非常有用的工具,用于实时监控系统中进程的资源使用情况。它会动态显示各个进程的 CPU 使用率、内存使用率等信息。你可以通过在终端中输入 top 命令来启动 top 工具。在 top 界面中,你可以按不同的键来对进程进行排序,例如按 P 键按 CPU 使用率排序,按 M 键按内存使用率排序。

另外,htop 是一个更高级的进程监控工具,它提供了更友好的界面和更多的功能。你可以通过包管理器安装 htop,然后在终端中输入 htop 来使用它。htop 不仅可以显示进程的资源使用情况,还可以方便地对进程进行操作,如终止进程、调整优先级等。

进程管理与作业控制的实际应用场景

  1. 系统维护脚本 在系统维护过程中,经常需要运行一些长时间运行的脚本,如备份脚本、日志清理脚本等。通过将这些脚本作为后台作业运行,可以在不影响其他工作的情况下完成系统维护任务。例如,以下是一个简单的备份脚本:
#!/bin/bash
DATE=$(date +%Y%m%d)
tar -zcvf /backup/backup_$DATE.tar.gz /var/www/html

你可以将这个脚本保存为 backup_script.sh,并通过以下命令在后台运行:

chmod +x backup_script.sh
./backup_script.sh &

这样,备份过程会在后台进行,你可以继续在终端中执行其他操作。

  1. 多任务处理 在开发过程中,你可能需要同时运行多个服务或测试不同的组件。通过作业控制,你可以方便地在前台和后台切换不同的任务。例如,假设你正在开发一个 Web 应用,你可能需要同时运行前端开发服务器和后端 API 服务器。你可以在后台启动前端开发服务器:
npm run start:frontend &

然后在前台启动后端 API 服务器:

python app.py

如果需要切换到前端开发服务器的控制台输出,可以使用 fg 命令将其切换到前台。

  1. 自动化任务调度 借助 Bash 的进程管理和作业控制功能,结合 cron 等任务调度工具,可以实现自动化任务调度。例如,假设你需要每天凌晨 2 点运行一次系统清理脚本。你可以先创建一个清理脚本 cleanup_script.sh
#!/bin/bash
rm -rf /var/log/*.log

然后,通过编辑 crontab 文件(使用 crontab -e 命令),添加以下行来设置任务调度:

0 2 * * * /path/to/cleanup_script.sh &

这样,系统会在每天凌晨 2 点自动运行清理脚本,并将其作为后台作业执行,避免影响系统的正常使用。

总结

在 Bash 中,进程管理与作业控制是非常重要的功能,它们为用户提供了灵活、高效地管理和运行程序的能力。通过掌握进程的启动、前台与后台运行、作业控制、进程终止、进程间通信以及守护进程等知识,你可以更好地利用系统资源,提高工作效率。无论是系统管理员进行系统维护,还是开发人员进行多任务开发和自动化任务调度,这些技能都具有极高的实用价值。在实际应用中,根据不同的需求选择合适的进程管理和作业控制方法,将有助于优化系统性能,确保各项任务顺利完成。同时,要注意合理使用进程资源,避免因进程过多或资源占用过高导致系统性能下降。通过不断实践和探索,你将更加熟练地运用这些技术,为你的工作带来更大的便利。