Linux 软件包管理与作业控制 – 实践练习

发布: (2025年12月27日 GMT+8 07:33)
12 min read
原文: Dev.to

Source: Linux Package Management – Job Control Practice Exercises (Dev.to)

请提供您希望翻译的完整文本(除代码块和 URL 之外),我将为您翻译成简体中文并保留原有的格式。

Exercise 1 – Job vs Process

Goal

了解 Bash 中 job(作业)与 process(进程)的区别,以及为什么管道算作单个作业。

Background

  • Process – 正在运行的程序实例,由 PID 标识。
  • Job – Bash 一起管理的一个或多个进程的集合(例如管道)。
  • Bash 为每个作业分配一个 job ID%1%2、…),可以使用作业控制内建命令(fgbgjobskill)来引用它们。

Source:

第 1 部分 – Bash 作业与进程控制

1️⃣ 列出当前作业

jobs
  • 如果没有显示任何作业,请先启动一些后台任务(见第 2 步)。

2️⃣ 启动一些后台作业

# 简单的 sleep 命令
sleep 60 &          # 作业 %1
sleep 120 &        # 作业 %2

# 一个管道(算作单个作业)
yes | head -n 1000000 > /dev/null &
  • 使用 jobs -l 验证作业,可看到 作业 IDPID

3️⃣ 将作业切换到前台

fg %1   # 将 %1 替换为想要的作业 ID
  • 注意,此时命令会占用终端,直到它完成或你将其挂起(Ctrl+Z)。

4️⃣ 挂起前台作业并在后台恢复它

# 当作业在前台运行时,按 Ctrl+Z
# Bash 会报告类似信息: [1]+  Stopped   sleep 60

bg %1   # 在后台恢复被挂起的作业
  • 使用 jobs -p 只列出后台作业的 PID。

5️⃣ 终止作业

kill %2          # 向作业 %2 发送 SIGTERM
kill -9 %2       # 若未正常退出,则强制杀死
  • jobs 确认作业已消失。

6️⃣ 验证管道是单个作业

# 在后台启动管道
{ yes | head -n 500000 > /dev/null; } &
jobs -l
  • Bash 会报告 一个 作业 ID,尽管管道会创建两个进程(yeshead)。这两个 PID 都列在同一个作业下。

摘要检查清单

  • 使用 jobsjobs -l 列出作业。
  • 使用 & 启动后台作业。
  • 使用 fg 将作业带到前台。
  • Ctrl+Z 暂停并用 bg 恢复。
  • 使用 kill 终止作业。
  • 注意管道算作单个作业。

进一步阅读

  • Bash 参考手册 – Job Control
  • man bashJOB CONTROL 部分
  • man kill, man fg, man bg, man jobs

Exercise 1 – Job vs Process (Foreground job)

Goal

了解 job(作业)与 process(进程)的区别,以及为什么管道算作单个作业。

Task

ping -c 5 google.com | wc -l

Observe

  • 创建了两个进程pingwc
  • 创建了一个作业:整个管道被视为单个命令。

Why it matters

  • Bash 作业控制针对 作业 而不是单个进程进行操作。
  • 了解这一点有助于在调试或管理管道时做出正确判断。

Exercise 2 – 前台作业阻塞 Shell

任务

ping google.com

运行该命令,然后尝试输入另一条命令。

观察

  • Shell 被阻塞。
  • 所有键盘输入都发送到 ping 进程。

停止方法

Ctrl + C

生产相关性

长时间运行的前台命令会阻塞自动化脚本并阻止后续命令的执行。

练习 3 — 后台作业 (&)

任务

ping -c 10 google.com &

观察

  • Shell 立即返回提示符。
  • ping 输出继续异步出现。

检查作业列表

jobs

为什么重要

在后台运行命令而未妥善处理输出,可能会使终端或日志文件变得杂乱。根据需要使用作业控制(jobsfgbgkill)或重定向输出。

练习 4 – 重定向后台输出

任务

ping -c 10 google.com > ping.log &

观察

  • 没有终端噪音。
  • 输出已安全地捕获到 ping.log 中。

生产环境相关性

为后台作业重定向输出是生产环境中的标准做法。

练习 5 — 使用 /dev/null

任务

ping google.com > /dev/null &

观察

  • 命令的输出会被完全丢弃。

原因

在健康检查或保持活跃的脚本中很方便,因为你不需要任何输出。

练习 6 — 工作列表

任务

jobs

启动多个作业

ping google.com > /dev/null &
ping bing.com   > /dev/null &

观察

作业 ID([1][2]、…)出现。

练习 7 – 将作业置于前台 (fg)

任务

fg %1

停止方法

Ctrl + C

关键规则

只有 前台作业 会接收键盘信号。

练习 8 — 挂起作业(Ctrl + Z

任务

ping google.com
# press Ctrl+Z
jobs

观察

作业状态:已停止

练习 9 — 在后台恢复作业 (bg)

任务

bg %1
jobs

观察

  • 作业再次运行。
  • 它仍然不接受键盘输入。

练习 10 — 终止作业

任务

kill %1

强制终止

kill -9 %1

生产相关性

安全地终止失控的作业。

练习 11 — wait 命令

任务

ping -c 5 google.com > /dev/null &
ping -c 5 bing.com   > /dev/null &
wait
echo "All jobs finished"

观察

echo 仅在两个 ping 命令完成后才运行。

原因

演示在 shell 脚本中使用 wait 对并行执行进行控制。

练习 12 – wait -n(任意作业完成)

任务

ping -c 10 google.com > /dev/null &
ping -c 3 bing.com   > /dev/null &
wait -n
echo "One job finished"

练习 13 — 使用终端响铃进行通知

任务

ping -c 5 google.com > /dev/null &
wait
tput bel
echo "Download complete"

为什么?
在长时间运行的手动任务完成时提供可听的提示。

Exercise 14 — nohup 在注销后仍然存活

Task

nohup ping -c 30 google.com > nohup.out &
exit
  1. 再次登录。
  2. 验证 ping 进程仍在运行:
ps aux | grep ping

Observation

ping 作业在你注销后仍然继续运行。

Production Relevance

对于必须在用户会话结束后仍保持运行的远程服务器操作非常有用(例如,长时间运行的脚本、后台服务)。

练习 15 — 父进程更改(重新父化)

任务

ps -o pid,ppid,cmd -p <pid>

观察

注销后,父 PID 会变为 1(init 进程)。

第 2 部分 — RPM(低层包管理)

练习 16 – 在不安装的情况下检查 RPM

rpm -qpl zsh*.rpm

列出该软件包将会安装的文件。

练习 17 — 手动安装 RPM

sudo rpm -i zsh*.rpm

不会执行依赖关系解析。

练习 18 – 删除 RPM

sudo rpm -e zsh

演示了仅使用 RPM 在生产环境中可能带来的风险(不会自动处理依赖或配置文件)。

第3部分 — DNF核心使用

练习19 — 搜索软件包

dnf search links

练习20 — 安装及其依赖

sudo dnf install links

练习21 — 删除软件包

sudo dnf remove links

练习22 — 仓库感知

dnf info neofetch

显示哪个仓库提供了该软件包。

第 4 部分 — 软件仓库 (BaseOS, AppStream, …)

练习 23 – 列出仓库

dnf repolist

练习 24 – 启用 CRB

sudo dnf config-manager --set-enabled crb

练习 25 – 启用 EPEL

sudo dnf install epel-release

安装 htop

sudo dnf install htop

第 5 部分 – 依赖分析

练习 26 – 包提供了什么

dnf repoquery --provides bash

练习 27 – 包需要什么

dnf repoquery --requires bash

练习 28 – 谁需要该包

dnf repoquery --whatrequires bash

练习 29 – 弱依赖(推荐)

dnf repoquery --recommends gimp

练习 30 – 安装时不包含弱依赖

sudo dnf install gimp --setopt=install_weak_deps=False

练习 31 – 反向弱依赖(补充)

dnf repoquery --what-supplements langpacks-de

第 6 部分 — 依赖移除的风险

练习 32 — 依赖自动移除问题

# Install Matplotlib (which pulls in NumPy)
sudo dnf install python3-matplotlib

# Verify NumPy works
python3 -c "import numpy"

# Remove Matplotlib
sudo dnf remove python3-matplotlib

# Verify NumPy again
python3 -c "import numpy"

在移除 python3-matplotlib 后,应用会崩溃,因为 numpy 是作为 依赖 安装的,并随之被自动删除。

练习 33 — 使用 dnf mark install 进行修复

# Install NumPy explicitly
sudo dnf install python3-numpy

# Mark it as a manually‑installed package so it isn’t auto‑removed
sudo dnf mark install python3-numpy

# Now remove Matplotlib safely
sudo dnf remove python3-matplotlib

通过将 python3-numpy 标记为手动安装的包,即使其依赖的包 (python3-matplotlib) 被移除,它仍会保留在系统中。

Part 7 – 更新、降级和版本锁定

练习 34 – 系统升级

sudo dnf upgrade

练习 35 – 降级软件包

  1. 列出该软件包的所有可用版本:

    dnf list python3 --showduplicates
  2. 降级到所需版本(将 <VERSION> 替换为您想要的确切版本号):

    sudo dnf downgrade python3-<VERSION>

练习 36 – 临时升级排除

sudo dnf upgrade --exclude=python3*

第 8 部分 – 自动更新

练习 37 – 启用自动更新

  1. 安装 dnf-automatic 软件包:

    sudo dnf install dnf-automatic
  2. 启用并启动计时器:

    sudo systemctl enable --now dnf-automatic.timer

练习 38 – 配置仅安全更新

  1. 打开配置文件进行编辑:

    sudo vi /etc/dnf/automatic.conf
  2. 设置以下选项(将它们放在相应的节下,例如 [commands]):

    upgrade_type = security
    apply_updates = yes

注意: 新设置将在下次计时器运行时生效。若要立即应用更新,可运行 sudo dnf-automatic --upgrade

Source:

第9部分 — DNF 模块

练习 39 – 列出模块

dnf module list

练习 40 – 启用 Node.js 流

sudo dnf module enable nodejs:18
sudo dnf upgrade
node --version

练习 41 – 安装模块配置文件

sudo dnf module install nodejs:18/development

练习 42 – 移除模块配置文件

sudo dnf module remove nodejs:18/development

练习 43 – 禁用并重置模块

sudo dnf module disable nodejs
sudo dnf module reset nodejs

第10部分 — 依赖冲突调试

练习44 — 损坏的 RPM 安装

sudo dnf install https://example.com/foreign.rpm

分析

使用以下命令识别缺失的依赖项:

dnf repoquery --whatprovides <package-name>

第11部分 — Snap 包

练习 45 – 安装 Snap

sudo dnf install snapd
sudo systemctl enable --now snapd.socket

练习 46 – 通过 Snap 安装 Firefox

sudo snap install firefox
snap run firefox

练习 47 – 比较版本

firefox --version
snap run firefox --version

Snap 版 Firefox 更新。

Back to Blog

相关文章

阅读更多 »