「速通Shell」常用命令(下)—— 归档、权限与进阶工具

前两篇讲了文件与文本、进程与网络,把 shell 编程日常打交道的高频命令过了一大半。这一篇是这个系列的最后一部分,讲剩下的三块内容:归档压缩、权限用户、还有一些进阶工具。

这三块命令的特点是"用得不多但每次都要查",归档一年可能就用几次,权限脚本天天用但参数容易忘,xargs 和 cron 这种工具型命令用好了能省很多事。读完这一篇,三篇常用命令系列就完整了。

一、归档与压缩

归档和压缩在 shell 里是两个动作:归档是把多个文件合成一个(用 tar),压缩是把单个文件变小(用 gzip、xz 等)。日常我们用 tar 同时做这两件事------tar 本身不压缩,但可以调用 gzip 或 xz 一起做。

1.1 tar:归档

tar 是 tape archive 的缩写,源自磁带备份时代。现代 tar 的核心用途是把目录打包成一个文件。

bash 复制代码
# 打包
tar -cf archive.tar dir/
​
# 解包
tar -xf archive.tar
​
# 查看内容
tar -tf archive.tar

这几个是最基础的用法。但日常我们更常用"打包+压缩":

bash 复制代码
# 打包并用 gzip 压缩
tar -czf archive.tar.gz dir/
​
# 打包并用 xz 压缩(更小但更慢)
tar -cJf archive.tar.xz dir/
​
# 打包并用 bzip2 压缩
tar -cjf archive.tar.bz2 dir/
​
# 解压(tar 自动识别压缩格式)
tar -xzf archive.tar.gz
tar -xJf archive.tar.xz
tar -xjf archive.tar.bz2

几个常用选项

  • -c:创建归档
  • -x:解压归档
  • -t:列出归档内容
  • -v:详细输出(列出处理的文件)
  • -f:指定文件名(必须紧跟文件名,比如 -f archive.tar)
  • -C:解压到指定目录
  • --exclude:排除某些文件
  • -z:gzip 压缩
  • -j:bzip2 压缩
  • -J:xz 压缩
  • -p:保留权限

几个实战组合

bash 复制代码
# 打包并排除某些文件
tar -czf backup.tar.gz --exclude='*.log' --exclude='tmp/' /var/data/
​
# 打包并显示进度
tar -czf - dir/ | pv > archive.tar.gz
​
# 解压到指定目录
tar -xzf archive.tar.gz -C /opt/
​
# 解压单个文件(不解压整个归档)
tar -xzf archive.tar.gz path/inside/file.txt
​
# 追加文件到现有 tar(不常用)
tar -rf archive.tar newfile.txt

tar 的一个细节-f 必须紧跟文件名,不能分开写 -f file.tar-zcvf-zcfv 等价,但 -zvfc 是不行的。

1.2 各种压缩格式的取舍

python 复制代码
# gzip:默认选择,平衡速度和压缩率
gzip file.txt          # 压缩(会删除原文件)
gunzip file.txt.gz     # 解压
​
# bzip2:压缩率比 gzip 高,速度慢
bzip2 file.txt
bunzip2 file.txt.bz2
​
# xz:压缩率最高,速度最慢
xz file.txt
unxz file.txt.xz
​
# zip:跨平台(Windows 也认),压缩率一般
zip -r archive.zip dir/
unzip archive.zip

压缩格式的取舍:

  • gzip:最快,压缩率中等,日常首选,.tar.gz.tgz 后缀。
  • bzip2:比 gzip 小一点,比 gzip 慢一点,.tar.bz2
  • xz:压缩率最高,但慢得多。适合一次压缩、多次解压的场景(比如发布包)。
  • zip:跨平台(Windows、macOS 都认),但 shell 脚本里 tar 更主流。

建议日常备份、传输用 gzip,需要发版本包、长期归档用 xz,需要跟 Windows 共享用 zip。

1.3 7z:高压缩率

7z 是 7-Zip 的命令行版本,压缩率比 xz 还高一点。

bash 复制代码
# 安装
apt install p7zip-full    # Debian/Ubuntu
yum install p7zip         # CentOS/RHEL
​
# 压缩
7z a archive.7z dir/
​
# 解压
7z x archive.7z

7z 适合"必须最小"的场景(嵌入式系统、网络传输受限),日常用得少。

二、权限与用户

权限是 Linux 系统的基础设施。shell 脚本里打交道最多的权限相关命令是 chmod、chown、umask、sudo。这一节把这几个讲清楚。

2.1 文件权限的基础

在讲命令之前,先快速回顾 Linux 文件权限。ls -l 的第一列是权限位:

sql 复制代码
-rw-r--r-- 1 user group 1024 Jan 1 12:00 file.txt
drwxr-xr-x 2 user group 4096 Jan 1 12:00 dir/

权限位分四组解读:

  • 第 1 位:文件类型(- 普通文件、d 目录、l 链接)
  • 第 2-4 位:所有者(user)权限
  • 第 5-7 位:所属组(group)权限
  • 第 8-10 位:其他人(other)权限

每组三位分别是:读 r(4)、写 w(2)、执行 x(1)。数字表示是把三个权限位的值加起来。

2.2 chmod:改权限

bash 复制代码
# 数字模式
chmod 755 file.sh        # rwxr-xr-x
chmod 644 file.txt       # rw-r--r--
chmod 600 secret.key     # rw-------
chmod 700 private/       # rwx------
​
# 符号模式
chmod u+x file.sh        # 所有者加执行权限
chmod g-w file.txt       # 所属组去掉写权限
chmod o=r file.txt       # 其他人只设读权限
chmod a+r file.txt       # 所有人都加读权限
chmod +x script.sh       # 简写:所有人加执行权限

几个常见权限:

  • 644:文件默认权限,所有者可读写,其他人只读。
  • 755:可执行文件或目录的默认权限,所有人可执行(对目录意味着可进入)。
  • 600:私有文件(如密钥),只有所有者能读写。
  • 700:私有目录(如 .ssh),只有所有者能进入。

批量改权限

bash 复制代码
# 把目录下所有 .sh 加上可执行
find . -name "*.sh" -exec chmod +x {} ;
​
# 递归设目录为 755,文件为 644(很常见的部署场景)
find /opt/myapp -type d -exec chmod 755 {} ;
find /opt/myapp -type f -exec chmod 644 {} ;

2.3 chown / chgrp:改所有者和组

bash 复制代码
# 改所有者
chown alice file.txt
​
# 改所有者和组
chown alice:developers file.txt
​
# 改组(只改组)
chgrp developers file.txt
​
# 递归改
chown -R alice:developers /opt/myapp/

chown 只能由 root 执行,普通用户不能改自己文件的所有者,组的话要看用户是不是组成员。

2.4 umask:默认权限

umask 是"用户文件创建掩码"------它决定新创建的文件和目录的默认权限。

bash 复制代码
# 查看当前 umask
umask
# 输出:0022
​
# 设置 umask
umask 022

umask 的算法:默认权限减去 umask。

  • 文件默认权限是 666
  • 目录默认权限是 777
  • 实际权限 = 默认权限 - umask

例如 umask 022 时:

  • 新文件:666 - 022 = 644
  • 新目录:777 - 022 = 755

建议:服务器上 umask 通常是 0022,安全场景用 0077(只有自己能看)。脚本里如果要严格控制文件权限,可以临时改 umask:

bash 复制代码
old_umask=$(umask)
umask 077
# 接下来创建的文件都是 600 权限
touch secret.key
umask "$old_umask"

2.5 sudo / su:提权

sudo 让普通用户以 root(或别的用户)身份执行命令。

bash 复制代码
# 以 root 身份执行
sudo apt update
​
# 以别的用户身份执行
sudo -u alice whoami
​
# 切换到 root shell
sudo -i
sudo su -
​
# 编辑文件(需要权限时)
sudo vim /etc/nginx/nginx.conf
​
# 列出当前用户能 sudo 的命令
sudo -l

sudo 使用时需要注意安全

  • 永远不要 sudo chmod 777------这是给所有人完全权限,生产环境出事故的常见原因
  • sudo 不是"万能钥匙"------它受 /etc/sudoers 配置限制,用户必须有权限才能 sudo
  • 远程操作重要服务时,避免直接 sudo,改用专门的运维账号

su 是 switch user 的缩写,跟 sudo 区别是:

  • sudo 是"借权限",输入自己的密码
  • su 是"切换身份",需要目标用户的密码(root 用户切换不需要)

日常推荐用 sudo------可以审计、可配置、不需要共享 root 密码。

2.6 id / groups:查身份

bash 复制代码
# 当前用户信息
id
# 输出:uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo)
​
# 只看 UID
id -u
​
# 只看组
id -g
​
# 列出所有组
groups

id 在脚本里很常用------判断当前是不是 root:

bash 复制代码
if [ "$(id -u)" -ne 0 ]; then
    echo "请用 root 运行此脚本" >&2
    exit 1
fi

三、进阶工具

最后这一组是工具型命令,它们本身不直接做事,但能放大其他命令的能力。

3.1 xargs:把 stdin 变成参数

xargs 是 shell 里最容易被低估的命令之一。它解决"命令参数太长怎么办"和"组合命令"两个问题。

bash 复制代码
# 最常见用法:find + xargs + 命令
find . -name "*.log" | xargs rm
​
# 等价但更安全(处理文件名含空格的情况)
find . -name "*.log" -print0 | xargs -0 rm

-print0-0 配合用 null 字符分隔------这是处理"文件名含空格"的安全模式。

bash 复制代码
# 每个文件执行一次命令
echo "file1 file2 file3" | xargs -n 1 cp -- /tmp/
​
# 并行执行
find . -name "*.jpg" | xargs -P 4 -I {} convert {} -resize 50% {}.small.jpg

-P N 是"用 N 个进程并行执行"------这是 xargs 做并发任务的关键。

bash 复制代码
# 用占位符指定参数位置
find . -name "*.sh" | xargs -I {} chmod +x {}
​
# 处理包含特殊字符的输入
echo "name with spaces" | xargs -d '\n' touch

xargs 跟 find -exec 的取舍:

  • xargs 性能更好(一次调用处理多个文件),但要小心文件名特殊字符
  • -exec 更安全(每个文件单独调用),但慢

默认用 find ... -print0 | xargs -0 ... 模式,又快又安全。

3.2 tee:一箭双雕

tee 把 stdin 同时输出到 stdout 和文件,既能在屏幕看到,又能保存到日志。

bash 复制代码
# 同时输出到屏幕和文件
ls -la | tee output.log
​
# 追加(不覆盖)
ls -la | tee -a output.log
​
# 用 sudo 保存到需要权限的文件
echo "127.0.0.1 example.com" | sudo tee -a /etc/hosts

sudo + tee 的经典用法:

bash 复制代码
# 把内容写到 root 拥有的文件
echo "新的配置" | sudo tee /etc/myapp.conf >/dev/null

> /dev/null 抑制 tee 自身的输出,只保留写文件的效果。

3.3 crontab:定时任务

crontab 是 Linux 的定时任务工具。语法是 crontab -e 编辑、crontab -l 查看、crontab -r 删除。

cron 的时间格式:分 时 日 月 周 命令

bash 复制代码
# 每天凌晨 3 点跑
0 3 * * * /opt/backup.sh
​
# 每 5 分钟跑
*/5 * * * * /opt/monitor.sh
​
# 每周一上午 9 点
0 9 * * 1 /opt/weekly.sh
​
# 每月 1 号凌晨
0 0 1 * * /opt/monthly.sh

几个特殊写法:

  • *:每(每分、每时、每天......)
  • */N:每 N(每 5 分钟、每 2 小时)
  • 1,3,5:1 点、3 点、5 点
  • 1-5:1 到 5(连续)

crontab 的几个坑

  1. 环境变量不同:crontab 默认的 PATH 很有限,脚本里要用绝对路径
  2. 输出不会显示:crontab 的输出默认会发邮件,现代服务器没有本地邮件------用 >> /var/log/cron.log 2>&1 重定向
  3. 工作目录不同:crontab 的工作目录是 $HOME,脚本里要 cd 到正确目录

实操建议:写一个 crontab 行时,明确所有路径:

javascript 复制代码
0 3 * * * /bin/bash /opt/backup.sh >> /var/log/backup.log 2>&1

3.4 screen / tmux:终端复用

screen 和 tmux 是"终端复用器"------让你在一个终端里开多个窗口,断开后能恢复。

tmux 是新一代标准,比 screen 配置更灵活,如果有 tmux 就用 tmux。

bash 复制代码
# 启动新会话
tmux
​
# 启动命名会话
tmux new -s mywork
​
# 列出所有会话
tmux ls
​
# 重新连接
tmux attach -t mywork
​
# 在会话里:
# Ctrl+B 然后 c:创建新窗口
# Ctrl+B 然后 n:下一个窗口
# Ctrl+B 然后 p:上一个窗口
# Ctrl+B 然后 d:分离会话(detach)

screen 跟 tmux 类似的快捷键(Ctrl+A 替代 Ctrl+B)。

核心场景 :远程操作时启动一个长期任务,用 screen/tmux 保护它不被断开中断。比如升级服务时 screen -S upgrade,跑完后再 screen -r upgrade 看结果。

3.5 watch:周期执行

watch 每隔一段时间执行一次命令,用来观察变化。

bash 复制代码
# 每 2 秒看一次磁盘
watch -n 2 df -h
​
# 每秒看一次进程
watch -n 1 "ps aux | grep nginx"
​
# 高亮变化的部分
watch -d "ls -la /tmp/"
​
# 退出码非 0 时停止
watch -e "curl -sf https://api.example.com/health"

watch 是动态监控的好工具,比手动重复命令省事。

3.6 其他值得知道的工具

at :一次性定时任务。at 23:00 进入交互模式,输入命令,Ctrl+D 结束。比 crontab 简单,但用得不多。

script :记录终端会话。script -t timing.log session.log,退出后用 scriptreplay 回放。

timeout :限时执行。timeout 30 long_command,30 秒后发 TERM,超时保护。

bash 复制代码
# 给命令加超时
timeout 10 curl -s https://slow-api.example.com
​
# 5 秒后还没下载完就 kill
timeout 5 wget https://example.com/big-file.iso

envsubst :环境变量替换。echo "Hello $NAME" | envsubst 会把 $NAME 替换成环境变量值。

arduino 复制代码
# 渲染配置模板
envsubst < config.template > config.conf

四、总结

这一篇我们讲完了 shell 常用命令系列的最后一部分------归档、权限、进阶工具。三篇系列合起来,覆盖了日常 95% 的工具场景。

三篇内容回顾:

第一篇讲的是文件操作和文本处理------ls、cp、find、cat、less、head、tail、sort、uniq、cut、paste、tr、join 。

第二篇讲的是进程、网络、系统信息------ps、top、kill、nohup、ping、curl、ssh、scp、rsync、ss、dig、nc、date、free、df 。

第三篇(这一篇)讲的是归档、权限、进阶工具------tar、gzip、chmod、chown、sudo、xargs、tee、crontab、tmux 。

三篇读下来,应该对 shell 日常命令有了完整印象,知道什么时候用哪个、怎么组合。

相关推荐
吴声子夜歌21 小时前
Shell编程实例——bash入门
linux·运维·shell
Swizard1 天前
Linux 日志神器 journalctl 完全指南:彻底替代传统日志查看方式
shell
吴声子夜歌2 天前
Shell编程——数组
linux·运维·shell
吴声子夜歌2 天前
Shell编程——开发规范
linux·运维·shell
吴声子夜歌3 天前
Shell编程——if条件语句
linux·运维·shell
吴声子夜歌3 天前
Shell编程——条件测试与比较
linux·运维·shell
吴声子夜歌3 天前
Shell编程——函数
linux·运维·shell
吴声子夜歌6 天前
Shell脚本——流程控制:for循环
linux·运维·shell
吴声子夜歌6 天前
Shell脚本——数组
linux·运维·shell
吴声子夜歌7 天前
编写Shell脚本——自顶向下设计
linux·运维·shell