Linux 常用命令行
以下所介绍的部分命令,在设备上是由适合嵌入式 Linux 的工具集 BusyBox 提供,行为和 Linux 桌面发行版上不完全一致,这里均采用 BusyBox 所提供的指令用法。
¶ifconfig:查看接口状态
ifconfig
可设置网卡接口的状态,或是显示目前的设置。以下是一些主要的设置参数。
语法格式:ifconfig < -a > [网卡名称] <参数>
参数 | 作用 |
---|---|
add <地址> | 设置网卡的IPv6地址。 |
del <地址> | 删除网卡的IPv6地址。 |
up | 启动指定的网卡。 |
down | 关闭指定的网卡。 |
metric <数目> | 指定在计算数据包的转送次数时,所要加上的数目。 |
mtu <字节> | 设置网卡的MTU(最大数据包大小)。 |
netmask <子网掩码> | 设置网卡的子网掩码。 |
-broadcast <地址> | 将要送往指定地址的数据包当成广播数据包来处理。 |
[IP地址] | 指定网卡的IP地址。 |
直接输入 ifconfig
就会列出目前已激活的网卡,不论这个卡是否有给予 IP ,都会被显示出来。带接口的 ifconfig eth0
则仅会表示接口 eth0 的相关数据,无论其是否启动。使用 -a
选项,则会展示所有网卡的属性。
¶示例
1 | ifconfig ra8 |
展示的各项数据由上而下、由左而右分别代表:
- ra8:网卡的代号,也有
lo
这个 loopback 代表本地回环; - HWaddr:网卡的硬件地址,即 MAC ;
- inet addr:IPv4 地址,后面的 Bcast,Mask 分别代表的是广播地址 broadcast 与子网掩码 netmask ,这里没有体现;
- inet6 addr:IPv6 地址,Scope 代表该地址的作用域;
- 网络状态:UP 代表网卡已开启;BROADCAST 代表支持广播;RUNNING 代表网卡正在运行中;MULTICAST代表支持组播;
- MTU:最大传输单元,单位是字节;
- Metric:路由算法的度量值;
- RX:代表网络由启动到目前为止的数据包接收情况,packets 代表数据包数、errors 代表数据包发生错误的数量、dropped 代表由于有问题而遭丢弃的数据包数量等等;
- TX:与 RX 相反,代表网络由启动到目前为止的传送情况;
- collisions:代表数据包碰撞的情况,如果发生太多次,表示网络状况不太好;
- txqueuelen:代表用来传输资料的缓冲区的储存长度;
- RX bytes/TX bytes:总接收、传送的字节总量。
通过观察这些数据,可以大致了解你的网络情况。尤其是 RX , TX 内的 error 数量,以及是否发生严重的 collision 情况,都是值得注意的。
¶brctl:查看网桥状态
brctl
命令用于设置、维护和检查 Linux 内核中的以太网网桥配置。
以太网网桥是一种设备,通常用于将以太网的不同网络连接在一起,以便这些以太网对参与者显示为一个以太网。所连接的每个以太网对应于网桥中的一个物理接口。这些单独的以太网被聚集成一个更大的“逻辑”以太网,这个更大的以太网对应于网桥网络接口。
语法格式:brctl [参数] <网桥名>
参数 | 作用 |
---|---|
addbr | 创建网桥 |
delbr | 删除网桥 |
addif | 将网卡接口接入网桥 |
delif | 删除网桥接入的网卡接口 |
show | 查询网桥信息 |
stp {on|off} | 启用禁用 STP |
showstp | 查看网桥 STP 信息 |
setfd | 设置网桥延迟 |
showmacs | 查看 mac 信息 |
¶示例
1 | 使用 addbr 参数创建网桥: |
无线驱动较少关注网桥,但当出现 WiFi 无法连接的情况时,有可能是网桥出现了问题,比如对应的无线接口没有被加入到网桥中。此时可以通过 brctl show
指令查看网桥状态进行确认。
¶ps:查看进程状态
1 | ps --help |
直接执行 ps
,将打印正在执行的进程列表。
对于每个进程,默认显示这四列属性:
- PID:进程的PID
- USER:进程的所有者用户ID
- TIME:进程消耗的CPU时间总和
- COMMAND:进程由何种命令启动,包括所用的参数(args)
如果想自定义 ps
显示的列,可以使用 -o
参数。提示中所述的可选项目有很多,其中比较有用的除了默认的四项外,还有:
- stat:用不同的字符表示进程的状态。如 R 为可运行状态( Runnable ,正在运行或准备运行), S 为睡眠状态( Sleep ,等待某事件发生后继续运行), D 为不可中断状态( Disk Sleep ,等待 I/O 操作)等等
- vsz:进程分配的的虚拟内存,即进程可以访问的所有内存
- rss:进程的常驻内存集,即进程的物理内存占用,其中包括进程所使用的共享库占用的内存
- ppid:父进程的 PID
- etime: e 代表 Elapsed (经过), etime 是进程的挂钟时间 (wall-clock-time) ,即进程启动后经过的时间
¶示例
grep -v "\[.*\]"
是为了排除掉由内核创建的进程。
1 | ps -o pid,stat,time,rss,args | grep -v "\[.*\]" |
¶top:动态查看进程状态
1 | top --help |
top
的功能和 ps
差不多,但只要不手动退出,它就会自动刷新进程的占用情况(默认间隔5s)。
如 help 提示,在 top
界面中,可以用按键切换不同的排序和显示数据。需要注意 VSZ 和 RSS 的区别,进程的物理内存占用 RSS 只有按 S 后才会显示出来。
¶示例
1 | Mem: 255692K used, 181472K free, 180K shrd, 17092K buff, 65480K cached |
¶uptime:查看运行时间和平均负载
uptime
的功能非常简单,它打印出一行信息,包括:
- 当前时间
- 系统已运行时间
- 用户连接数,是总连接数而不是用户数
- 过去1/5/15分钟的平均负载
平均负载指的是处于可运行状态和不可中断状态,即 ps
或 top
中状态为 R 或 D 的平均进程数。
当平均负载与机器的逻辑核心数基本相等时,说明每个核心上都在运行程序,性能被充分发挥。如果平均负载明显高于逻辑核心数,则说明机器的性能已经不够了。
¶示例
1 | 一台服务器的 uptime 和逻辑核心数 |
¶tcpdump:抓包工具
tcpdump 是一个强大且复杂的本地抓包工具,限于篇幅,这里仅作简单介绍。
1 | tcpdump -h |
¶抓包选项
-c:指定要抓取的包数量。注意,是最终要获取这么多个包。例如,指定 -c 10
将获取10个包,但可能已经处理了100个包,只不过只有10个包是满足条件的包。
-i interface:指定监听接口。若未指定该选项,将从系统接口列表中搜寻编号最小的已配置好的接口(不包括 loopback 接口,要抓取 loopback 接口使用 tcpdump -i lo
),一旦找到第一个符合条件的接口,搜寻马上结束。可以使用 any
关键字表示所有网络接口。
-n:对地址以数字方式显式,否则显式为主机名,也就是说 -n
选项不做主机名解析。
-nn:除了 -n
的作用外,还把端口显示为数值,否则显示端口服务名。
-Q:指定要抓取的包是流入还是流出的包。可以给定的值为 in
、out
和 inout
,默认为 inout
。
-s len:设置 tcpdump
的数据包抓取长度为len,如果不设置默认将会是65535字节。对于要抓取的数据包较大时长度设置不够可能会产生包截断,若出现包截断,输出行中会出现 [|proto]
的标志(proto 实际会显示为协议名)。但是抓取len越长,包的处理时间越长,并且会减少 tcpdump
可缓存的数据包的数量,从而会导致数据包的丢失,所以在能抓取我们想要的包的前提下,抓取长度越小越好。
¶输出选项
-e:输出的每行中都将包括数据链路层头部信息,例如源 MAC 和目标 MAC 。
-q:快速打印输出。即打印很少的协议相关信息,从而输出行都比较简短。
-X:输出包的头部数据,会以16进制和 ASCII 两种方式同时输出。
-XX:输出包的头部数据,会以16进制和 ASCII 两种方式同时输出,更详细。
-v, -vv, -vvv:当分析和打印的时候,产生不同详细程度的输出。
¶其他功能性选项
-D:列出可用于抓包的接口。将会列出接口的数值编号和接口名,它们都可以用于 -i
后。
-F:从文件中读取抓包的表达式。若使用该选项,则命令行中给定的其他表达式都将失效。
-w:将抓包数据输出到文件中而不是标准输出。可以同时配合 -G time
选项使得输出文件每time秒就自动切换到另一个文件。可通过 -r
选项载入这些文件以进行分析和打印。
-r:从给定的数据包文件中读取数据。使用 -
表示从标准输入中读取。
¶过滤器
在选项之后,可以使用多种过滤器组成的表达式来指定要抓取怎样的包,一些常用的过滤方式如下。
¶根据主机过滤:
1 | 抓取所有经过 eth1 ,目的或源地址是192.168.1.1的网络数据 |
¶根据端口过滤:
1 | 抓取所有经过 eth1 ,目的或源端口是25的网络数据 |
¶根据协议过滤:
1 | 比较严谨的方式是根据协议号来过滤。 |
¶分析 tcpdump 的抓包结果
不建议使用 tcpdump
本身的打印来进行分析。
tcpdump
使用 -w
选项输出的 .pcap 类型文件可以用 Wireshark 或 OmniPeek 打开,进行详尽的分析。
¶tftp:简单文件传输协议
1 | tftp --help |
TFTP (Trivial File Transferring Protocol) 用于进行简单的文件传输,由于占用很小,比较适合在电脑与嵌入式设备之间传输文件。
在 Windows 上,可以通过 tftpd64 软件使用 tftp 。
将 tftpd64 设置为 Tftp Server 模式,配置工作目录(需要配置一个具有读写权限的目录),即可在对端设备上进行文件传输操作。
1 | 将本地文件 lancc.log 上传到192.168.1.11的 tftp 工作目录处 |
¶chmod:更改文件权限
chmod
是 CHange MODe 的缩写。使用 tftp
等方法将可执行文件、 Shell 脚本等传输到单板上时,这些文件可能不具备执行权限,此时就需要用 chmod
命令进行调整。
在Linux中使用 ls -l
以长格式列出文件时,能看到每行最前面有10个用于表示文件模式(权限)的字符:
1 | lrwxrwxrwx 1 root root 7 Jun 28 2021 cat -> busybox |
其中,第1个字符表示文件类型:
属性 | 文件类型 |
---|---|
- | 普通文件 |
d | 目录文件 |
l | 符号链接,其所指向的文件的属性才是真实的属性 |
c | 字符设备文件 |
b | 块设备文件 |
s | 套接字文件 |
p | 管道文件 |
后面的9个字符被称为文件属性,第2-4,5-7,8-10个字符分别代表文件的所有者、所属群组、其他所有用户对文件的操作权限。
属性 | 权限 |
---|---|
r | 读权限Read |
w | 写权限Write |
x | 执行权限eXecute(执行脚本,进入目录) |
如果用4代表r,2代表w,1代表x,0代表无权限,则可以用一个八进制数来表示一种权限。3个这样的八进制数,就能代表9个字符的文件属性,然后用 chmod
进行修改。如:
1 | 修改文件权限为rwxr-xr-- |
¶xargs:批量执行命令
xargs
命令可以将标准输入转为命令行参数。真正要执行的命令紧跟在 xargs
后面,接受其传来的参数。
语法格式:xargs [-options] [command]
1 | 将管道左侧的标准输入,转为命令行参数,传给xargs后面的echo命令 |
使用 xargs
的必要性在于,许多命令(比如 rm
、 mkdir
、 ls
)要与管道一起使用时,都需要通过它将标准输入转为命令行参数。下面这个管道的使用例中,如果不加 xargs
就会报错,提示 mkdir
缺少操作参数:
1 | echo "one two three" | xargs mkdir |
xargs
适合与 find
命令组合使用。先用 find
找出符合一定条件的条件,再用 xargs
对这些文件进行处理。
由于 xargs
默认将空格作为分隔符,这不适合直接处理文件名,因为文件名可能包含空格。但 find
命令有一个特别的参数 -print0
,可以指定输出的文件列表以 null 分隔。同时,用 xargs
命令的 -0
参数可以表示将 null 当作分隔符,这样就能形成很好的配合。
1 | 删除 /tmp 路径下的所有通常文件 |
还有一个原因,使得 xargs
特别适合 find
命令。有些命令(比如 rm
)一旦参数过多会报错“参数列表过长”,而无法执行,改用 xargs
就没有这个问题,因为它会对每个参数执行一次命令。
1 | 找出所有 txt 文件后,对每个文件搜索其中任意大小写形式的 wifi |
-I
选项用于指定一个替换字符串(比如{}
),这个字符串在 xargs
扩展时会被替换掉,当 -I
与 xargs
结合使用,每一个参数命令都会被执行一次:
1 | 将当前目录下所有 log 文件通过 tftp 传输到192.168.1.11 |
¶history:查看历史命令
history
用于查看当前用户的历史执行命令。
1 | history |
¶tail:输出文件结尾
tail
默认输出文件的最后10行。配合选项 -f
,即可随文件增长即时输出新增数据。这使得它很适合用来监测日志。
1 | 在后台监测wifi_drv.log的新增内容 |
¶nohup:退出终端后保持命令运行
nohup
即 NO Hang UP,用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行。适合在编译代码时使用,这样开始编译后即使本地断开连接甚至关机,服务器上也会继续进行编译任务。
nohup
命令在默认情况下(非重定向时),会输出一个名叫 nohup.out 的文件到当前目录下,如果当前目录的 nohup.out 文件不可写,则将输出重定向到 $HOME/nohup.out 文件中。
1 | 可以在编译大量代码时使用 |
¶gdb:GNU 调试器
gdb
的功能非常强大,堪称让开发者对运行中的程序拥有了上帝视角。它的用法很多,这里简单介绍如何用 GDB 排查程序异常退出的问题。
如果在编译代码时加入-g
编译选项,且没有用 -s
或 -S
等选项除去调试符号,则生成的程序可以使用 GDB 进行调试。若编译时设置优化等级为 -O0
不开启优化,还可以用 GDB 的 s
(step) 指令进行单步调试。
1 | gcc -g hello.c -o hello |
如果需要调试指定的进程下的子线程,可以使用 ps -T
查看子线程的信息,编码时可以给每个线程设置名称,这样在ps -T
时就可以对线程进行区分。
1 | 用 -p 选项指定 pid,调试 hello 进程 |
GDB 接管成功后,执行 r
(run) 命令,或者 c
(continue) 命令,接着正常执行导致问题进程异常退出的用例即可,GDB 接管后不会影响进程的正常运行。
一旦接管的进程发生异常退出问题,GDB 就会收到到调试信号将进程停住。这时候只需要用 bt
(backtrace) 命令查看调用栈、用 p
(print) 命令将函数中的变量打印出来等方法即可对问题点进行分析。
接管进程成功后也可以通过 b
(break) 命令设置断点进行调试,触发条件满足即可将进程暂停,查看、修改函数的入参和局部变量,进行动态调试。
另外,假如有程序异常终止,系统一般会报出 “core dumped”,并生成文件名以 core
开头的核心转储文件。这种文件保存了程序退出时进程地址空间的内容以及有关进程状态的其他信息,可以用 GDB 配合程序进行调试。
例如下图中对 MTK 方案 SDK 中主管 Band Steering 的程序 bs20
进行调试:
用 bt
指令查看函数调用栈,可以得知程序退出是在 mapfilter_init
函数中调用了 memcpy
导致的。虽然由于编译时没有加 -g
选项,这里不会显示出具体是代码中的哪一行,但基本上已经能定位到直接问题点了。
¶Shell 脚本调试
Shell 提供了一些用于调试脚本的选项,如下所示:
选项 | 作用 |
---|---|
-n | 读一遍脚本中的命令但不执行,用于检查脚本中的语法错误 |
-v | 一边执行脚本,一边将执行过的脚本命令打印到标准错误输出 |
-x | 提供跟踪执行信息,将执行的每一条命令和结果依次打印出来 |
使用这些选项有三种方法,一是执行脚本时在命令行提供参数:
1 | sh -x ./script.sh |
二是在脚本开头用 Shebang (#!
) 提供参数:
1 |
第三种方法是在脚本中用 set
命令启用或禁用参数:
1 |
|
这里 set -x
和 set +x
分别表示启用和禁用 -x
参数,这样可以只对脚本中的某一段进行跟踪调试。
更多实用内容可参考《Linux命令行大全》(人民邮电出版社)。