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 个实战场景。
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,动态链接) |
| 内置 Shell | busybox 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 / 9base suckless 风格极简工具集,每命令独立小文件 定制最小 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 清理)。
六、参考链接
- BusyBox 官网(The Swiss Army Knife of Embedded Linux):https://www.busybox.net/
- BusyBox 关于页(设计目标与机制说明):https://www.busybox.net/about.html
- 官方预编译静态二进制下载(各架构):https://www.busybox.net/downloads/binaries/
- Ubuntu 22.04(jammy)busybox 手册页:https://manpages.ubuntu.com/manpages/jammy/en/man1/busybox.1.html
- BusyBox 源码在线浏览(各 applet 实现与配置项):https://git.busybox.net/busybox/
- Debian Wiki busybox 条目:https://wiki.debian.org/busybox