busybox 命令详解与参数实测(Ubuntu 22.04)

基于 Ubuntu 22.04(BusyBox 1.30.1)逐形态实测 busybox:无参用法全表与 249 个 applet 清单(--list/--list-full)、单二进制分发机制(703K 对照 GNU 108M)、核心 applet 调用与 GNU 差异五连实证(--time-style/-P/yesterday/asort/静默 sed)、ash 子 Shell 与 httpd 最小静态服务器、--install -s 符号链接安装排障,附救援自检等 4 个实战场景。

Linux命令Linux系统UbuntuUbuntu 22.04命令行Shell2026/10/16

busybox 命令详解与参数实测(Ubuntu 22.04)

目标:全面掌握 busybox 的用法——无参用法帮助全表、--list/--list-full 两级 applet 清单、单二进制多命令分发机制、ash/sh 内置 Shell、httpd 最小静态 Web 服务器、--install -s 符号链接全量安装、与 GNU 全功能版命令的参数差异实证、救援自检与打包校验等组合场景,全部命令与回显已在 Ubuntu 22.04(BusyBox 1.30.1)实测通过。

一、环境信息

本文所有命令与回显均在以下环境实测采集,读者在相同版本的 Ubuntu 上可直接复现:

项目实测值
操作系统Ubuntu 22.04.5 LTS
架构x86_64
内核6.8.0-138-generic
busybox 包版本1:1.30.1-7ubuntu3.1
BusyBox 上游版本v1.30.1(multi-call binary)
主二进制/bin/busybox(703K,动态链接)
内置 Shellbusybox ash(系统 /bin/sh 仍为 dash,未被替换)
演示目录/root/demo/busybox
依赖libc6 (>= 2.34)(apt-cache show 实测,仅此一项)

环境确认命令与实测回显如下:

$ head -2 /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"

$ uname -m
x86_64

$ dpkg -l busybox | tail -1
ii  busybox        1:1.30.1-7ubuntu3.1 amd64        Tiny utilities for small and embedded systems

$ busybox | head -1
BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3.1) multi-call binary.

busybox 默认未随 Ubuntu 桌面/最小服务器安装,用 apt 一条命令即可装齐(实测安装过程,仅解包 busybox 一个包):

$ DEBIAN_FRONTEND=noninteractive apt-get install -y -qq busybox
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package busybox.
(Reading database ... 26482 files and directories currently installed.)
Preparing to unpack .../busybox_1%3a1.30.1-7ubuntu3.1_amd64.deb ...
Unpacking busybox (1:1.30.1-7ubuntu3.1) ...
Setting up busybox (1:1.30.1-7ubuntu3.1) ...

💡 说明:busybox 是「多合一二进制」(multi-call binary)——一个可执行文件内嵌了几十个常用 Unix 命令的实现,按「调用时使用的名字」分发到对应功能。它是嵌入式设备、系统救援盘、initramfs 开机早期环境里的事实标准工具箱。

💡 技术拓展:multi-call binary 这类「单文件装多命令」的同类实现主要有——

实现特点典型适用场景
BusyBox约 250 个 applet,GPLv2,体积极小,嵌入式事实标准initramfs、救援盘、路由器固件、最小系统
Toybox约 400 个命令,BSD 许可,Android 官方采用Android 的 adb shell 环境
sbase / 9basesuckless 风格极简工具集,每命令独立小文件定制最小 Unix 环境
GNU coreutils + util-linux功能最全、参数最多,命令分散为独立二进制常规桌面与服务器

本文主角是 BusyBox v1.30.1,Ubuntu 仓库版本 1:1.30.1-7ubuntu3.1。

二、命令概览

2.1 语法与测试数据

busybox 的调用语法只有五种形态(摘自实测的无参用法输出,见 2.2 节):

Usage: busybox [function [arguments]...]
   or: busybox --list[-full]
   or: busybox --show SCRIPT
   or: busybox --install [-s] [DIR]
   or: function [arguments]...

五种形态的含义与本文的实测覆盖情况:

形态含义实测小节
busybox [function [arguments]...]以 busybox 开头调用某个内嵌命令(applet)3.4
busybox --list列出全部 applet 名称(每行一个)3.1
busybox --list-full列出带安装路径的 applet 名称3.2
busybox --show SCRIPT显示脚本中用到的 applet二、概览提及
busybox --install [-s] [DIR]在目录下为全部 applet 建符号链接(-s 为软链接)3.8
function [arguments]...以 applet 名直接调用(需先做符号链接安装)3.8

💡 说明:applet 是 BusyBox 对「内嵌命令」的官方称呼,一个 applet 对应一个命令实现(如 ls、ash、httpd),后文沿用该词。

测试数据全部放在 /root/demo/busybox 下(新建,不影响系统其他目录):

$ mkdir -p /root/demo/busybox/www

$ echo 'hello busybox' > /root/demo/busybox/hello.txt

$ printf 'line1 apple\nline2 banana\nline3 cherry\n' > /root/demo/busybox/fruits.txt

$ ls -la /root/demo/busybox
total 20
drwxr-xr-x  3 root root 4096 Oct 16 00:18 .
drwxr-xr-x 67 root root 4096 Oct 16 00:18 ..
-rw-r--r--  1 root root   38 Oct 16 00:18 fruits.txt
-rw-r--r--  1 root root   14 Oct 16 00:18 hello.txt
drwxr-xr-x  2 root root 4096 Oct 16 00:18 www

演示数据共三个文件:hello.txt(单行文本)、fruits.txt(三行「行号+水果名」文本)、www/ 目录(后面 httpd 演示的站点根目录)。

2.2 用法输出全表(--help 等效 / 无参数)

busybox 的帮助输出有两条等价途径:busybox --help 与无参数直接执行,两者输出完全相同——版本、版权、调用语法与当前编译进的全部 applet 清单。先看 --help 的头部实测:

$ busybox --help | head -12
BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3.1) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Licensed under GPLv2. See source distribution for detailed
copyright notices.

Usage: busybox [function [arguments]...]
   or: busybox --list[-full]
   or: busybox --show SCRIPT
   or: busybox --install [-s] [DIR]
   or: function [arguments]...

	BusyBox is a multi-call binary that combines many common Unix

再以无参数形态取全量输出(先看总行数,再贴全表):

$ busybox 2>&1 | wc -l
45

全表共 45 行,逐行照抄如下:

$ busybox 2>&1
BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3.1) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Licensed under GPLv2. See source distribution for detailed
copyright notices.

Usage: busybox [function [arguments]...]
   or: busybox --list[-full]
   or: busybox --show SCRIPT
   or: busybox --install [-s] [DIR]
   or: function [arguments]...

	BusyBox is a multi-call binary that combines many common Unix
	utilities into a single executable.  Most people will create a
	link to busybox for each function they wish to use and BusyBox
	will act like whatever it was invoked as.

Currently defined functions:
	[, [[, acpid, adjtimex, ar, arch, arp, arping, ash, awk, basename, bc,
	blkdiscard, blockdev, brctl, bunzip2, bzcat, bzip2, cal, cat, chgrp,
	chmod, chown, chpasswd, chroot, chvt, clear, cmp, cp, cpio, cttyhack,
	cut, date, dc, dd, deallocvt, depmod, devmem, df, diff, dirname, dmesg,
	dnsdomainname, dos2unix, du, dumpkmap, dumpleases, echo, egrep, env,
	expand, expr, factor, fallocate, false, fatattr, fgrep, find, fold,
	free, freeramdisk, fsfreeze, fstrim, ftpget, ftpput, getopt, getty,
	grep, groups, gunzip, gzip, halt, head, hexdump, hostid, hostname,
	httpd, hwclock, i2cdetect, i2cdump, i2cget, i2cset, id, ifconfig,
	ifdown, ifup, init, insmod, ionice, ip, ipcalc, ipneigh, kill, killall,
	klogd, last, less, link, linux32, linux64, linuxrc, ln, loadfont,
	loadkmap, logger, login, logname, logread, losetup, ls, lsmod, lsscsi,
	lzcat, lzma, lzop, md5sum, mdev, microcom, mkdir, mkdosfs, mke2fs,
	mkfifo, mknod, mkpasswd, mkswap, mktemp, modinfo, modprobe, more,
	mount, mt, mv, nameif, nc, netstat, nl, nologin, nproc, nsenter,
	nslookup, nuke, od, openvt, partprobe, paste, patch, pidof, ping,
	ping6, pivot_root, poweroff, printf, ps, pwd, rdate, readlink,
	realpath, reboot, renice, reset, resume, rev, rm, rmdir, rmmod, route,
	rpm, rpm2cpio, run-init, run-parts, sed, seq, setkeycodes, setpriv,
	setsid, sh, sha1sum, sha256sum, sha512sum, shred, shuf, sleep, sort,
	ssl_client, start-stop-daemon, stat, strings, stty, svc, svok, swapoff,
	swapon, switch_root, sync, sysctl, syslogd, tac, tail, tar, taskset,
	tee, telnet, test, tftp, time, timeout, top, touch, tr, traceroute,
	traceroute6, true, truncate, tty, ubirename, udhcpc, udhcpd, uevent,
	umount, uname, uncompress, unexpand, uniq, unix2dos, unlink, unlzma,
	unshare, unxz, unzip, uptime, usleep, uudecode, uuencode, vconfig, vi,
	w, watch, watchdog, wc, wget, which, who, whoami, xargs, xxd, xz,
	xzcat, yes, zcat

逐段解读这份 45 行输出:

段落行数范围内容
版本与版权第 1~4 行上游版本 v1.30.1、Ubuntu 打包修订号 1:1.30.1-7ubuntu3.1、GPLv2 许可
Usage 语法第 6~10 行五种调用形态(见 2.1 节表格)
机制说明第 12~15 行multi-call binary 的分发原理:按调用名分发
applet 清单第 17~45 行Currently defined functions: 之后以逗号分隔列出全部内嵌命令

注意「无参输出」里的 applet 清单是逗号分隔的粗排形态;要拿到精确总数与规整清单,用下一节的 --list(实测总数 249 个)。

2.3 版本信息

版本确认有两个权威来源,实测回显如下:

$ busybox | head -1
BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3.1) multi-call binary.

$ dpkg -l busybox | tail -1
ii  busybox        1:1.30.1-7ubuntu3.1 amd64        Tiny utilities for small and embedded systems

版本号的构成:v1.30.1 是 BusyBox 上游版本,(Ubuntu 1:1.30.1-7ubuntu3.1) 中的 1:1.30.1-7ubuntu3.1 是 Debian/Ubuntu 打包修订号(1: 为 epoch,7ubuntu3.1 为打包版本,.1 是安全点更新)。

再用 apt-cache 确认包的依赖关系(busybox 只依赖 libc6,这也是它能进 initramfs/最小环境的原因之一):

$ apt-cache show busybox | grep -E '^(Package|Version|Depends|Conflicts|Replaces)'
Package: busybox
Version: 1:1.30.1-7ubuntu3.1
Replaces: busybox-static
Depends: libc6 (>= 2.34)
Conflicts: busybox-static

两个版本信息命令的结论一致:本环境为 BusyBox v1.30.1,Ubuntu 打包版本 1:1.30.1-7ubuntu3.1。

三、参数逐项实测

3.1 --list:全部 applet 名称清单

busybox --list 每行输出一个 applet 名,便于脚本统计与批量处理。先给总数,再看首尾节选:

$ busybox --list | wc -l
249

$ busybox --list | head -30
[
[[
acpid
adjtimex
ar
arch
arp
arping
ash
awk
basename
bc
blkdiscard
blockdev
brctl
bunzip2
bzcat
bzip2
cal
cat
chgrp
chmod
chown
chpasswd
chroot
chvt
clear
cmp
cp
cpio

$ busybox --list | tail -8
who
whoami
xargs
xxd
xz
xzcat
yes
zcat

要点:本环境共编译进 249 个 applet,按字母序输出;从 [(test 命令的等价符号)到 zcat,覆盖文件操作、文本处理、压缩、网络、进程管理、Shell 等常用门类。用 busybox --list | grep 名称 可以快速判断某个命令是否被本机的 busybox 支持,这是救援环境里最常用的自检动作。

3.2 --list-full:带安装路径的 applet 形态

--list-full 在每个 applet 前加上「符号链接安装时应处的目录」,用于了解 busybox 设计上的标准布局:

$ busybox --list-full | wc -l
249

$ busybox --list-full | head -12
bin/[
bin/[[
sbin/acpid
sbin/adjtimex
usr/bin/ar
bin/arch
sbin/arp
usr/sbin/arping
bin/ash
usr/bin/awk
usr/bin/basename
usr/bin/bc

$ busybox --list-full | tail -6
usr/bin/xargs
usr/bin/xxd
usr/bin/xz
usr/bin/xzcat
usr/bin/yes
bin/zcat

对第一段路径做分组统计,可以看到 busybox 的标准目录布局:

$ busybox --list-full | cut -d/ -f1 | sort | uniq -c
     76 bin
      1 linuxrc
     46 sbin
    126 usr

统计解读:bin/ 76 个(开机就必须可用的核心命令,如 cat、ls、sh)、sbin/ 46 个(系统管理类,如 ifconfig、init)、usr/ 合计 126 个(usr/bin 与 usr/sbin 下的常规命令)、另有 1 个顶层形态 linuxrc(早期 Linux 初始化辅助程序)。四个数字相加正好 249,与 --list 总数吻合。

3.3 单二进制分发机制:703K 装下 249 个命令

本节用体积与文件类型实测,解释「一个二进制如何变成 249 个命令」。先看 /bin/busybox 本体:

$ ls -lh /bin/busybox
-rwxr-xr-x 1 root root 703K Aug 13  2024 /bin/busybox

$ file /bin/busybox | cut -c1-130
/bin/busybox: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2

作为对照,看一下 Ubuntu 上全功能 GNU 命令集(coreutils、util-linux、grep、sed、gawk 等)在 /usr/bin 下的合计体积:

$ du -sh /usr/bin
108M	/usr/bin

703K 对 108M——单文件 busybox 以约 1/150 的磁盘体积覆盖了 249 个常用命令的「够用版」实现。它没有替换系统的任何命令:系统 /bin/sh 依然指向 dash,busybox 只是静静地躺在 /bin/busybox 里等人调用:

$ ls -lh /bin/sh
lrwxrwxrwx 1 root root 4 Mar 23  2022 /bin/sh -> dash

$ readlink /bin/sh
dash

分发机制一句话概括:busybox 启动后读取 argv[0](即被调用时的程序名)与 argv[1](busybox 后的第一个词),去内嵌的 applet 注册表里匹配对应实现并跳转执行。于是同一个 703K 文件,叫它 busybox ls 就表现成 ls,把符号链接命名为 md5sum 再执行,它就表现成 md5sum(符号链接形态的实测见 3.8 节)。

💡 技术拓展:单文件工具箱有两类链接形态,选型时按「是否依赖动态库」取舍——

形态原理优点限制
动态链接版(本环境默认)二进制只含 applet 代码,运行时靠 glibc体积更小(703K),libc 共享内存中一份必须有可用的 ld-linux 与 libc
全静态版(busybox-static 包)libc 一并编进二进制任何同架构 Linux 内核上直接跑,不依赖任何库体积更大(实测 2.1M,见下)

救援盘/initramfs 里通常选全静态版,因为那类环境的根文件系统往往不完整。两包在 Ubuntu 中互为 Conflicts/Replaces(见 2.3 节 apt-cache 输出),同一台机器同时只能安装其一。

busybox-static 的 2.1M 体积为实测数据(安装该包时 /bin/busybox 会被其静态版接管,排障细节见第五章 Q3):

$ ls -lh /bin/busybox
-rwxr-xr-x 1 root root 2.1M Aug 13  2024 /bin/busybox

3.4 核心 applet 调用:busybox <命令> 形式

busybox 的日常用法就是「busybox + 命令名 + 参数」,命令行为与对应工具的精简版一致。以下逐一实测核心 applet,并与全功能版输出对照。

busybox ls(注意其长列表格式与 GNU ls 的列宽差异):

$ busybox ls -la /root/demo/busybox
total 20
drwxr-xr-x    3 root     root          4096 Oct 16 00:18 .
drwxr-xr-x   67 root     root          4096 Oct 16 00:18 ..
-rw-r--r--    1 root     root            38 Oct 16 00:18 fruits.txt
-rw-r--r--    1 root     root            14 Oct 16 00:18 hello.txt
drwxr-xr-x    2 root     root          4096 Oct 16 00:18 www

$ ls -la /root/demo/busybox | head -4
total 20
drwxr-xr-x  3 root root 4096 Oct 16 00:18 .
drwxr-xr-x 67 root root 4096 Oct 16 00:18 ..
-rw-r--r--  1 root root   38 Oct 16 00:18 fruits.txt

内容一致,但 busybox ls 的属主/组/大小列使用固定宽度对齐(root root 后多出空格),GNU ls 按内容自适应宽度——两个版本输出的「可解析性」差异在做脚本字段切分时要注意。

busybox cat / busybox grep / busybox sed / busybox awk:

$ busybox cat /root/demo/busybox/hello.txt
hello busybox

$ busybox grep -n apple /root/demo/busybox/fruits.txt
1:line1 apple

$ busybox sed 's/line/LINE/' /root/demo/busybox/fruits.txt
LINE1 apple
LINE2 banana
LINE3 cherry

$ busybox awk '{print $2}' /root/demo/busybox/fruits.txt
apple
banana
cherry

busybox tar(与 GNU tar 完全互操作:busybox 打包,GNU tar 解包验证):

$ cd /root/demo/busybox && busybox tar czf demo.tgz fruits.txt hello.txt; echo rc=$?
rc=0

$ ls -lh /root/demo/busybox/demo.tgz
-rw-r--r-- 1 root root 165 Oct 16 00:18 /root/demo/busybox/demo.tgz

$ tar tzf /root/demo/busybox/demo.tgz
fruits.txt
hello.txt

要点:busybox tar 生成的 gzip 压缩包,系统自带的全功能 tar 能正常列出内容,说明压缩格式与 tar 打包格式都是标准实现,跨版本交换文件没有兼容性问题。

3.5 与 GNU 全功能版的参数差异实证

busybox 是「够用就好」的实现,GNU 扩展参数大多缺失。本节选 4 个报错型差异加 1 个静默型差异逐一实证(两边同跑、回显对照)。

差异一:ls --time-style 不被支持。GNU ls 支持长选项 --time-style=long-iso 输出 ISO 日期;busybox ls 直接报错并带出自己的 usage:

$ ls --time-style=long-iso -l /root/demo/busybox/hello.txt; echo rc=$?
-rw-r--r-- 1 root root 14 2026-10-16 00:18 /root/demo/busybox/hello.txt
rc=0

$ busybox ls --time-style=long-iso /root/demo/busybox; echo rc=$?
ls: unrecognized option '--time-style=long-iso'
BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3.1) multi-call binary.

Usage: ls [-1AaCxdLHRFplinshrSXvctu] [-w WIDTH] [FILE]...

List directory contents

	-1	One column output
	-a	Include entries which start with .
	-A	Like -a, but exclude . and ..
	-x	List by lines
	-d	List directory entries instead of contents
	-L	Follow symlinks
	-H	Follow symlinks on command line
	-R	Recurse
	-p	Append / to dir entries
	-F	Append indicator (one of */=@|) to entries
	-l	Long listing format
	-i	List inode numbers
	-n	List numeric UIDs and GIDs instead of names
	-s	List allocated blocks
	-lc	List ctime
	-lu	List atime
	--full-time	List full date and time
	-h	Human readable sizes (1K 243M 2G)
	--group-directories-first
	-S	Sort by size
	-X	Sort by extension
	-v	Sort by version
	-t	Sort by mtime
	-tc	Sort by ctime
	-tu	Sort by atime
	-r	Reverse sort order
	-w N	Format N columns wide
	--color[={always,never,auto}]	Control coloring
rc=1

从 usage 可见 busybox ls 的完整选项集合:支持 -l、-a、-h、--full-time、--color 等,但没有 --time-style。需要 ISO 日期格式时用 --full-time 替代。

差异二:grep -P(Perl 正则)不支持:

$ grep -P 'app{1}le' /root/demo/busybox/fruits.txt; echo rc=$?
line1 apple
rc=0

$ busybox grep -P 'apple' /root/demo/busybox/fruits.txt; echo rc=$?
grep: invalid option -- 'P'
BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3.1) multi-call binary.

Usage: grep [-HhnlLoqvsriwFEz] [-m N] [-A/B/C N] PATTERN/-e PATTERN.../-f FILE [FILE]...

Search for PATTERN in FILEs (or stdin)

	-H	Add 'filename:' prefix
	-h	Do not add 'filename:' prefix
	-n	Add 'line_no:' prefix
	-l	Show only names of files that match
	-L	Show only names of files that don't match
	-c	Show only count of matching lines
	-o	Show only the matching part of line
	-q	Quiet. Return 0 if PATTERN is found, 1 otherwise
	-v	Select non-matching lines
	-s	Suppress open and read errors
	-r	Recurse
	-i	Ignore case
	-w	Match whole words only
	-x	Match whole lines only
	-F	PATTERN is a literal (not regexp)
	-E	PATTERN is an extended regexp
	-z	Input is NUL terminated
	-m N	Match up to N times per file
	-A N	Print N lines of trailing context
	-B N	Print N lines of leading context
	-C N	Same as '-A N -B N'
	-e PTRN	Pattern to match
	-f FILE	Read pattern from file
rc=2

busybox grep 只提供 BRE/ERE(-F 字面量、-E 扩展正则),没有 PCRE。需要 Perl 正则时留在 GNU grep 上处理。

差异三:date -d yesterday 这类自然语言日期不支持:

$ date -d yesterday +%F; echo rc=$?
2026-10-15
rc=0

$ busybox date -d yesterday +%F; echo rc=$?
date: invalid date 'yesterday'
rc=1

busybox date 的 -d 只接受数值形式的时间/增量描述,不认识 yesterday、next monday 这类自然语言。写跨版本脚本时,日期推算不要依赖 GNU 扩展。

差异四:busybox awk 缺少 gawk 的数组排序函数 asort(但注意:gawk 的字符串替换函数 gensub busybox awk 反而是支持的,实测输出 bAnAnA):

$ awk 'BEGIN{print gensub("a","A","g","banana")}'; echo rc=$?
bAnAnA
rc=0

$ busybox awk 'BEGIN{print gensub("a","A","g","banana")}'; echo rc=$?
bAnAnA
rc=0

$ awk 'BEGIN{split("c a b",x); print asort(x)}'; echo rc=$?
3
rc=0

$ busybox awk 'BEGIN{split("c a b",x); print asort(x)}'; echo rc=$?
awk: cmd. line:1: Call to undefined function
rc=1

差异实证说明:busybox awk 的函数集合与 gawk 是「交集」而非「子集/超集」关系——gensub 有、asort 无。移植 awk 脚本前要逐函数确认,最直接的办法就是像上面这样在两边各跑一遍。

差异五(静默型,最危险):sed 的 GNU 扩展范围地址 0,/re/ 不报错、直接不生效:

$ sed '0,/line2/s/line/LINE/' /root/demo/busybox/fruits.txt; echo rc=$?
LINE1 apple
LINE2 banana
line3 cherry
rc=0

$ busybox sed '0,/line2/s/line/LINE/' /root/demo/busybox/fruits.txt; echo rc=$?
line1 apple
line2 banana
line3 cherry
rc=0

GNU sed 的 0,/line2/ 表示「从第 0 行到第一个 line2」(含 line1 的替换,输出 LINE1);busybox sed 不认识这个扩展,既不报错也不替换,原样输出、退出码还是 0。静默差异比报错差异更需要警惕:脚本里判断退出码发现不了,必须在测试环境先验证替换结果。

汇总成对照表(全部维度均有上方实测回显支撑):

对照维度busybox 版(v1.30.1)GNU 全功能版(本环境)
二进制体积/bin/busybox 703K 单文件含 249 个命令coreutils/util-linux 等分散安装,/usr/bin 合计 108M
选项集合精简子集:ls 无 --time-style、grep 无 -P长选项与扩展齐全
awk 内置函数有 gensub、无 asort(实测)gawk 5.1.0 全支持
date 相对日期-d 不认 yesterday(实测报错)自然语言日期齐全
不认识的语法sed 静默跳过不执行、退出码 0(实测)明确执行或显式报错
ls 输出格式固定宽度对齐(属主/组列更宽)自适应宽度
适合场景initramfs、救援盘、嵌入式、最小化环境常规桌面/服务器与复杂文本处理

表选解读:交互使用几乎无感,脚本移植必须过一遍差异清单——重点是第 5 行「静默差异」,退出码救不了你,要在目标环境实测输出。

3.6 busybox ash / busybox sh:内置 Shell 实测

busybox 自带 POSIX Shell 实现 ash(busybox 里 sh 就是 ash 的别名,见 2.2 节清单两者都在)。喂一段脚本给 ash 子 Shell:

$ echo 'echo $0; uname -a; pwd' | busybox ash
ash
Linux f1034b9326b2 6.8.0-138-generic #138~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug  7 13:43:15 UTC  x86_64 x86_64 x86_64 GNU/Linux
/root/demo/busybox

回显解读:$0 是 ash(管道喂入的非登录 Shell 进程名);uname -a 与 pwd 正常执行,说明 ash 支持标准命令与内核信息查询。

再验证「ash 进程的本体就是 busybox」——打印该 Shell 自己的 /proc/<PID>/exe 链接(注意命令末尾补一条 echo done,避免 Shell 对末条命令做 exec 优化导致读到替换后的进程):

$ busybox sh -c 'echo shell=$0; ls -l /proc/$$/exe; echo done'
shell=sh
lrwxrwxrwx 1 root root 0 Oct 16 00:20 /proc/22752/exe -> /usr/bin/busybox
done

/proc/22752/exe -> /usr/bin/busybox 是单二进制机制的直接证据:名为 sh 的进程,可执行文件就是 /usr/bin/busybox(/bin 是 /usr/bin 的符号链接位置)。

ash 的语法能力实测(for 循环、变量展开正常):

$ busybox ash -c 'for i in 1 2 3; do echo i=$i; done'
i=1
i=2
i=3

要点:busybox sh 与 busybox ash 完全等价;用 busybox sh -c '命令' 可以在不安装任何符号链接的情况下跑一段「busybox 化」脚本,这正是救援环境临时救急的用法。

3.7 busybox httpd:一行命令的最小静态 Web 服务器

httpd 是 busybox 内嵌的小型 HTTP 服务器,一条命令就能起一个静态站点,常用于临时分享文件、嵌入式设备管理页。先看它的完整用法:

$ busybox httpd --help 2>&1 | head -20
BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3.1) multi-call binary.

Usage: httpd [-ifv[v]] [-c CONFFILE] [-p [IP:]PORT] [-u USER[:GRP]] [-r REALM] [-h HOME]
or httpd -d/-e/-m STRING

Listen for incoming HTTP requests

	-i		Inetd mode
	-f		Don't daemonize
	-v[v]		Verbose
	-p [IP:]PORT	Bind to IP:PORT (default *:80)
	-u USER[:GRP]	Set uid/gid after binding to port
	-r REALM	Authentication Realm for Basic Authentication
	-h HOME		Home directory (default .)
	-c FILE		Configuration file (default {/etc,HOME}/httpd.conf)
	-m STRING	MD5 crypt STRING
	-e STRING	HTML encode STRING
	-d STRING	URL decode STRING

实测启动:站点根目录为 /root/demo/busybox/www(已在 2.1 节创建),端口 8080,默认守护进程化(后台运行):

$ echo '<h1>busybox httpd demo</h1><p>Served by BusyBox 1.30.1 httpd</p>' > /root/demo/busybox/www/index.html

$ busybox httpd -p 8080 -h /root/demo/busybox/www; echo rc=$?
rc=0

验证进程与 HTTP 服务(curl 实测首页内容与响应头):

$ sleep 1; pidof busybox; echo rc=$?
22707
rc=0

$ curl -s http://127.0.0.1:8080/
<h1>busybox httpd demo</h1><p>Served by BusyBox 1.30.1 httpd</p>

$ curl -sI http://127.0.0.1:8080/ | head -5
HTTP/1.0 200 OK
Date: Fri, 16 Oct 2026 00:18:09 GMT
Connection: close
Content-type: text/html
Accept-Ranges: bytes

响应头解读:HTTP/1.0 200 OK 说明 httpd 只实现到 HTTP/1.0(对静态文件下载完全够用);Content-type: text/html 自动按扩展名推断 MIME 类型。

测试完成后杀掉进程,并验证端口确已关闭(curl 返回码 7 = 连接被拒绝):

$ kill $(pidof busybox); sleep 0.5; curl -s --max-time 2 http://127.0.0.1:8080/; echo rc=$?
rc=7

要点:busybox httpd -p 端口 -h 根目录 是世界最小的静态 Web 服务器启动方式;不加 -f 时后台守护运行,pidof busybox 找进程、kill 收尾。

3.8 busybox --install -s:符号链接全量安装

--install 把 249 个 applet 以符号链接形式批量「安装」到指定目录,之后就能像普通命令一样直接用名字调用。-s 表示符号链接(不加则是硬链接)。指定目录必须已存在,否则会出现本节第一段的批量报错(排障过程完整保留)。

直接对一个不存在的目录执行(实测报错形态,输出共 249 行同类报错,此处保留实测首尾):

$ busybox --install -s /root/demo/busybox/bin; echo rc=$?
busybox: /root/demo/busybox/bin/[: No such file or directory
busybox: /root/demo/busybox/bin/[[: No such file or directory
busybox: /root/demo/busybox/bin/acpid: No such file or directory
busybox: /root/demo/busybox/bin/adjtimex: No such file or directory
busybox: /root/demo/busybox/bin/ar: No such file or directory
busybox: /root/demo/busybox/bin/arch: No such file or directory
busybox: /root/demo/busybox/bin/arp: No such file or directory
busybox: /root/demo/busybox/bin/arping: No such file or directory
busybox: /root/demo/busybox/bin/ash: No such file or directory
busybox: /root/demo/busybox/bin/awk: No such file or directory
busybox: /root/demo/busybox/bin/basename: No such file or directory
busybox: /root/demo/busybox/bin/bc: No such file or directory
# (实测输出共 249 行同格式报错,每行仅 applet 名不同,此处保留实测首尾)
busybox: /root/demo/busybox/bin/xzcat: No such file or directory
busybox: /root/demo/busybox/bin/yes: No such file or directory
busybox: /root/demo/busybox/bin/zcat: No such file or directory
rc=0

⚠️ 注意:上面实测暴露了两个坑——--install 不会自动创建目标目录(249 个 applet 全部报 No such file or directory),而且逐个报错后退出码仍然是 0,脚本里不能靠 rc 判断安装是否成功。先 mkdir -p 再执行即可。

修正后重跑:先建目录,安装成功时无任何输出:

$ mkdir -p /root/demo/busybox/bin

$ busybox --install -s /root/demo/busybox/bin; echo rc=$?
rc=0

$ ls /root/demo/busybox/bin | wc -l
249

$ ls -l /root/demo/busybox/bin | head -6
total 0
lrwxrwxrwx 1 root root 16 Oct 16 00:20 [ -> /usr/bin/busybox
lrwxrwxrwx 1 root root 16 Oct 16 00:20 [[ -> /usr/bin/busybox
lrwxrwxrwx 1 root root 16 Oct 16 00:20 acpid -> /usr/bin/busybox
lrwxrwxrwx 1 root root 16 Oct 16 00:20 adjtimex -> /usr/bin/busybox
lrwxrwxrwx 1 root root 16 Oct 16 00:20 ar -> /usr/bin/busybox

安装后直接按名字调用 applet(符号链接分发机制的最终验证——md5sum 名字的链接,执行的就是 busybox 内嵌的 md5sum):

$ /root/demo/busybox/bin/md5sum /root/demo/busybox/hello.txt
67e00c65bb237ab153a34fa11c25a0a8  /root/demo/busybox/hello.txt

收尾删除实验安装目录(不影响 /bin/busybox 本体):

$ rm -rf /root/demo/busybox/bin; echo rc=$?
rc=0

要点:249 个链接全部指向 /usr/bin/busybox,数量与 --list 总数一致;这就是 BusyBox 在嵌入式系统「一个二进制 + 一堆软链接」的标准部署形态(busybox --install -s /bin 一步到位,但 Ubuntu 桌面/服务器不要这样做,会与 GNU 命令同名覆盖,见第五章 Q2)。

3.9 --help 与退出码行为

--help 输出与无参输出相同(版本、版权、Usage、applet 清单),取头部 12 行确认:

$ busybox --help | head -12
BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3.1) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Licensed under GPLv2. See source distribution for detailed
copyright notices.

Usage: busybox [function [arguments]...]
   or: busybox --list[-full]
   or: busybox --show SCRIPT
   or: busybox --install [-s] [DIR]
   or: function [arguments]...

	BusyBox is a multi-call binary that combines many common Unix

退出码行为实测三类:未知 applet 返回 127(与 Shell「命令未找到」约定一致)、applet 执行失败返回 1、applet 的退出码原样透传:

$ busybox nosuchcmd; echo rc=$?
nosuchcmd: applet not found
rc=127

$ busybox ls /nonexistent_dir; echo rc=$?
ls: /nonexistent_dir: No such file or directory
rc=1

$ busybox sh -c 'exit 3'; echo rc=$?
rc=3

要点:脚本中可用 rc=127 识别「这个 busybox 没编译进该命令」(换个精简固件时很有用);busybox sh -c 'exit 3' 返回 3 说明 busybox 不吞掉 applet 的退出码,管道与条件判断可正常使用。

四、实战示例

4.1 救援/最小环境自检三连

进入陌生救援环境(initramfs、单用户模式、维护 Shell)时,先用 busybox 自检「我是谁、系统跑多久、内存多少」。三个命令全部实测:

$ busybox uname -sm
Linux x86_64

$ busybox uptime
 00:23:08 up  6:20,  2 users,  load average: 1.71, 1.11, 0.72

$ busybox free
              total        used        free      shared  buff/cache   available
Mem:       41028028     7241980    27979528       30416     5806520    33713180
Swap:       2097148           0     2097148

要点:救援环境的 Shell 往往就是 busybox ash,命令前加不加 busybox 都能执行;busybox free 以 KB 为单位输出(GNU free 默认 MiB 且带表头说明),读数时注意单位。

4.2 busybox tar 打包 + 校验 + 解包还原链

用纯 busybox 完成一次「打包 → 校验 → 解包 → 比对」闭环,演示 tar/md5sum/sha256sum 三个 applet 协作:

$ busybox tar czf /root/demo/busybox/pkg.tgz -C /root/demo/busybox fruits.txt hello.txt; echo rc=$?
rc=0

$ busybox md5sum /root/demo/busybox/pkg.tgz
ceda89c34deb0ffbf57ab56205dfb95f  /root/demo/busybox/pkg.tgz

$ busybox sha256sum /root/demo/busybox/fruits.txt
6f576b57ab3671a9919b8062520777902eb4043ef1d2a83146172c9d631c2941  /root/demo/busybox/fruits.txt

$ mkdir -p /root/demo/busybox/restore && busybox tar xzf /root/demo/busybox/pkg.tgz -C /root/demo/busybox/restore && busybox ls -l /root/demo/busybox/restore
total 8
-rw-r--r--    1 root     root            38 Oct 16 00:18 fruits.txt
-rw-r--r--    1 root     root            14 Oct 16 00:18 hello.txt

要点:-C 指定打包/解包基准目录(busybox tar 支持);解包还原的两个文件与源文件大小一致(38/14 字节),md5 与 sha256 校验值可用于跨机传输后的完整性比对。

4.3 busybox httpd + busybox wget 自闭环下载验证

用两个 applet 组成一个「零依赖」下载验证链:httpd 提供服务,wget 抓取,hexdump 校验字节。适合在网络受限的最小环境里验证 HTTP 链路:

$ busybox httpd -p 8082 -h /root/demo/busybox/www; echo rc=$?
rc=0

$ sleep 0.5; busybox wget -q -O /tmp/fetched.html http://127.0.0.1:8082/index.html; echo rc=$?
rc=0

$ busybox cat /tmp/fetched.html
<h1>busybox httpd demo</h1><p>Served by BusyBox 1.30.1 httpd</p>

$ busybox hexdump -C /tmp/fetched.html | head -3
00000000  3c 68 31 3e 62 75 73 79  62 6f 78 20 68 74 74 70  |<h1>busybox http|
00000010  64 20 64 65 6d 6f 3c 2f  68 31 3e 3c 70 3e 53 65  |d demo</h1><p>Se|
00000020  72 76 65 64 20 62 79 20  42 75 73 79 42 6f 78 20  |rved by BusyBox |

$ kill $(pidof busybox); echo rc=$?
rc=0

要点:busybox wget -q -O 文件 URL 安静下载到指定文件;hexdump -C 的十六进制+ASCII 对照视图可确认下载内容逐字节正确(十六进制列 3c 68 31 3e 正好对应 ASCII 列 <h1>)。

4.4 busybox 文本处理管道:grep / awk / wc / sort / uniq

把 3.4 节的单命令用法串成管道,统计系统账号与其登录 Shell(grep 过滤注释 → awk 取第 1/7 字段 → head 截取 → wc 计数):

$ busybox grep -v '^#' /etc/passwd | busybox awk -F: '{print $1, $7}' | busybox head -5
root /bin/bash
daemon /usr/sbin/nologin
bin /usr/sbin/nologin
sys /usr/sbin/nologin
sync /bin/sync

$ busybox grep -v '^#' /etc/passwd | busybox awk -F: '{print $1, $7}' | busybox head -5 | busybox wc -l
5

$ printf 'b\na\nb\nc\n' | busybox sort | busybox uniq
a
b
c

要点:管道中每一段都显式写 busybox 前缀,是为了在混合环境(GNU 命令与 busybox 并存)下锁定行为版本;awk -F: 按冒号切字段、sort | uniq 经典去重组合在 busybox 中语义与 GNU 一致。

五、注意事项与常见问题

Q1:busybox --install -s 目录 报了一堆 No such file or directory,但退出码是 0,到底装没装上? 没装上。实测(3.8 节):目标目录不存在时,249 个 applet 逐个报错且最终 rc=0。--install 不负责创建目录,先 mkdir -p 再安装;安装成功的判据是「无输出 + ls 目录 | wc -l 等于 249」,不要依赖退出码。

Q2:Ubuntu 上装完 busybox,系统的 ls、cat 会被替换成 busybox 版吗? 不会。apt 安装的 busybox 包只提供 /bin/busybox 一个文件,不做符号链接安装,/bin/sh 也仍是 dash(3.3 节实测 readlink /bin/sh 为 dash)。想用 busybox 版某命令,用 busybox ls 显式形式最安全;不要在 Ubuntu 上执行 busybox --install -s /bin——249 个软链接会与 GNU 命令同名冲突,且 busybox 版参数是精简子集(3.5 节差异清单)。

Q3:误装了 busybox-static 之后 /bin/busybox 丢了,怎么恢复? 这是包互斥导致的,本机实测排障过程:busybox-static 与 busybox 互为 Conflicts/Replaces(2.3 节 apt-cache 输出),安装 busybox-static 时它会接管 /bin/busybox(静态版约 2.1M);卸载 busybox-static 时会连带卸载 busybox 包并删除 /bin/busybox。恢复办法:apt-get install -y busybox 重装即可,实测重装后 /bin/busybox 恢复为 703K 动态版(dpkg.log 可见仅解包安装 busybox 一个包)。

Q4:busybox 版 sed 执行了却「什么都没改」也没有报错,怎么排查? 先怀疑 GNU 扩展语法不被支持。实测(3.5 节差异五):sed '0,/re/' 这类扩展范围地址在 busybox 中静默跳过、退出码 0。排查三板斧:一是把同命令在 GNU 版上跑一遍对比输出;二是 busybox <命令> --help 查该 applet 支持的选项表;三是脚本里对关键替换用 grep 校验结果字符串 做断言,不要只看退出码。

Q5:为什么救援盘、路由器、initramfs 里到处是 busybox? 两个原因:一是体积,全静态版单文件 2.1M(实测)就把 249 个命令带齐,塞得进几 MB 的内存盘;二是自足,静态链接不依赖目标环境的 libc。Ubuntu 的开机早期环境(initramfs 阶段、恢复模式的救援 Shell)与各类嵌入式固件都按「busybox 二进制 + 一组符号链接」的方式提供最小命令集,这也是本文 --install -s(3.8 节)与 ash(3.6 节)两个机制的组合形态。Windows 侧的 WSL 轻量发行版、Buildroot/Yocto 构建的嵌入式根文件系统同样以 busybox 为默认工具箱。

Q6:想临时用 busybox 版命令又不想动系统,怎么做? 两种方式:一是每次显式 busybox <命令>(如 busybox ls -l),零副作用,本文所有示例都采用该形式;二是 busybox --install -s /专用目录 后把该目录临时前置到 PATH(PATH=/专用目录:$PATH 命令),适合批量验证「GNU 行为 vs busybox 行为」的差异,用完删目录即可(3.8 节收尾实测 rm -rf 清理)。

六、参考链接