Linux常用命令行小技巧
Category: 技术学习 | Tags: shell, linux | Source: Markdown ----------> Back to Wiki流畅地使用命令行是一个常被忽略的技能,或被认为是神秘的奥义。但是,它会以明显而微妙的方式改善你作为工程师的灵活度和生产力。这是我在 Linux 上工作时发现的有用的命令行使用小窍门和笔记的精粹。有些小窍门是很基础的,而有些是相当地特别、复杂、或者晦涩难懂。这篇文章不长,但是如果你可以使用并记得这里的所有内容,那么你就懂得很多了。
基础知识
学习基本
Bash技能。实际上,键入man bash,然后至少浏览一遍所有内容;它很容易理解,没那么长。其它shell也不错,但是Bash很强大,而且到处都可以找到(如果在你自己的笔记本上只学习zsh、fish之类,会在很多情形下受到限制,比如使用现存的服务器时)。至少学好一种基于文本的编辑器。理想的一个是
Vim(vi),因为在终端中编辑时随时都能找到它(即使大多数时候你在使用Emacs、一个大型的IDE、或一个现代的时髦编辑器)。学习怎样使用
man来阅读文档(好奇的话,用man man来列出分区号,比如1是常规命令,5是文件描述,8用于管理员)。用apropos找到帮助页。了解哪些命令不是可执行程序,而是Bash内置的,你可以用help和help -d得到帮助。学习使用
>和<来进行输出和输入重定向,以及使用|来管道重定向,学习关于stdout和stderr的东西。学习
*(也许还有?和{...})文件通配扩展和应用,以及双引号"和单引号'之间的区别。(更多内容请参看下面关于变量扩展部分)。熟悉
Bash作业管理:&, ctrl-z, ctrl-c,jobs,fg,bg,kill等等。掌握
ssh,以及通过ssh-agent,ssh-add等进行无密码验证的基础技能。基本的文件管理:
ls和ls -l(特别是,知道ls -l各个列的意义),less,head,tail和tail -f(或者更好的less +F),ln和ln -s(知道硬链接和软链接的区别,以及硬链接相对于软链接的优势),chown,chmod,du(用于查看磁盘使用率的快速摘要:du -sk *)。文件系统管理:df,mount,fdisk,mkfs,lsblk。基本的网络管理:
ip或ifconfig,dig。熟知正则表达式,以及各种使用
grep/egrep的选项。-i,-o,-A和-B选项值得掌握。学会使用
apt-get,yum,dnf或pacman(这取决于你的发行版)来查找并安装软件包。确保你可以用pip来安装基于Python的命令行工具(下面的一些东西可以很容易地通过pip安装)。
日常使用
在
Bash中,使用tab补完参数,使用ctrl-r来搜索命令历史。在
Bash中,使用ctrl-w来删除最后的单词,使用ctrl-u来删除整行,返回行首。使用alt-b和alt-f来逐词移动,使用ctrl-k来清除到行尾的内容,以及使用ctrl-l清屏。参见man readline来查看Bash中所有默认的键盘绑定,有很多。例如,alt-.可以循环显示先前的参数,而alt-扩展通配。另外,如果你喜欢
vi风格的键盘绑定,可以使用set -o vi。要查看最近用过的命令,请使用
history。 有许多缩写形式,比如!$(上次的参数)和!!(上次的命令),虽然使用ctrl-r和alt-.更容易些。返回先前的工作目录:
cd -。如果你命令输入到一半,但是改变主意了,可以敲
alt-#来添加一个#到开头,然后将该命令作为注释输入(或者使用快捷键ctrl-a, #,enter输入)。然后,你可以在后面通过命令历史来回到该命令。使用
xargs(或parallel),它很强大。注意,你可以控制每行(-L)执行多少个项目,以及并行执行(-P)。如果你不确定它是否会做正确的事情,可以首先使用xargs echo。同时,使用-I{}也很方便。样例:find . -name '*.py' | xargs grep some_function cat hosts | xargs -I{} ssh root@{} hostnamepstree -p对于显示进程树很有帮助。使用
pgrep和pkill来按名称查找进程或给指定名称的进程发送信号(-f很有帮助)。掌握各种可以发送给进程的信号。例如,要挂起进程,可以使用
kill -STOP [pid]。完整的列表可以查阅man 7 signal。如果你想要一个后台进程一直保持运行,使用
nohup或disown。通过
netstat -lntp或ss -plat检查哪些进程在监听(用于TCP,对UDP使用-u替代-t)。lsof来查看打开的套接字和文件。在
Bash脚本中,使用set -x调试脚本输出。尽可能使用严格模式。使用set -e在遇到错误时退出。也可以使用set -o pipefail,对错误进行严格处理(虽然该话题有点微妙)。对于更复杂的脚本,也可以使用trap。在
Bash脚本中,子shell(写在括号中的)是组合命令的便利的方式。一个常见的例子是临时移动到一个不同的工作目录,如:# 在当前目录做些事 (cd /some/other/dir; other-command) # 继续回到原目录注意,在
Bash中有大量的各种各样的变量扩展。检查一个变量是否存在:${name:?error message}。例如,如果一个Bash脚本要求一个单一参数,只需写input_file=${1:?usage: $0 input_file}。算术扩展:i=$(( (i + 1) % 5 ))。序列:{1..10}。修剪字符串:${var%suffix}和${var#prefix}。例如,if var=foo.pdf,那么echo ${var%.pdf}.txt会输出foo.txt。命令的输出可以通过
<(some command)作为一个文件来处理。例如,将本地的/etc/hosts和远程的比较:diff /etc/hosts <(ssh somehost cat /etc/hosts)了解
Bash中的“嵌入文档”,就像在cat <<EOF ...中。在
Bash中,通过:some-command >logfile 2>&1同时重定向标准输出和标准错误。通常,要确保某个命令不再为标准输入打开文件句柄,而是将它捆绑到你所在的终端,添加</dev/null是个不错的做法。man ascii可以得到一个不错的ASCII表,带有十六进制和十进制值两种格式。对于常规编码信息,man unicode,man utf-8和man latin1将很有帮助。使用
screen或tmux来复用屏幕,这对于远程ssh会话尤为有用,使用它们来分离并重连到会话。另一个只用于保持会话的最小可选方案是dtach。在
ssh中,知道如何使用-L或-D(偶尔也用-R)来打开端口通道是很有用的,如从一台远程服务器访问网站时。为你的
ssh配置进行优化很有用;例如,这个~/.ssh/config包含了可以避免在特定网络环境中连接被断掉的情况的设置、使用压缩(这对于通过低带宽连接使用scp很有用),以及使用一个本地控制文件来开启到同一台服务器的多通道:TCPKeepAlive=yes ServerAliveInterval=15 ServerAliveCountMax=6 Compression=yes ControlMaster auto ControlPath /tmp/%r@%h:%p ControlPersist yes其它一些与
ssh相关的选项对会影响到安全,请小心开启,如各个子网或主机,或者在信任的网络中:StrictHostKeyChecking=no,ForwardAgent=yes要获得八进制格式的文件的权限,这对于系统配置很有用而用
ls又没法查看,而且也很容易搞得一团糟,可以使用像这样的东西:stat -c '%A %a %n' /etc/timezone对于从另一个命令的输出结果中交互选择值,可以使用
percol。对于基于另一个命令(如
git)输出的文件交互,可以使用fpp(路径选择器)。要为当前目录(及子目录)中的所有文件构建一个简单的
Web服务器,让网络中的任何人都可以获取,可以使用:python -m SimpleHTTPServer 7777(使用端口7777和Python 2)。
文件处理
要在当前目录中按名称定位文件,
find . -iname '*something*'(或者相类似的)。要按名称查找任何地方的文件,使用locate something(但请记住,updatedb可能还没有索引最近创建的文件)。对于源代码或数据文件进行的常规搜索(要比
grep -r更高级),使用ag。要将
HTML转成文本:lynx -dump -stdin。对于
Markdown、HTML,以及各种类型的文档转换,可以试试pandoc。如果你必须处理
XML,xmlstarlet虽然有点老旧,但是很好用。对于
JSON,使用jq。对于
Excel或CSV文件,csvkit 提供了in2csv,csvcut,csvjoin,csvgrep等工具。对于亚马逊
S3,s3cmd会很方便,而s4cmd则更快速。亚马逊的aws则是其它AWS相关任务的必备。掌握
sort和uniq,包括 uniq 的-u和-d选项——参见下面的单行程序。掌握
cut,paste和join,它们用于处理文本文件。很多人会使用cut,但常常忘了join。了解
tee,它会将stdin同时复制到一个文件和stdout,如ls -al | tee file.txt。知道
locale会以微妙的方式对命令行工具产生大量的影响,包括排序的顺序(整理)以及性能。大多数安装好的Linux会设置LANG或其它locale环境变量为本地设置,比如像US English。但是,你要明白,如果改变了本地环境,那么排序也将改变。而且i18n过程会让排序或其它命令的运行慢好多倍。在某些情形中(如像下面那样的设置操作或唯一性操作),你可以安全地整个忽略缓慢的i18n过程,然后使用传统的基于字节的排序顺序export LC_ALL=C。了解基本的改动数据的
awk和sed技能。例如,计算某个文本文件第三列所有数字的和:awk '{ x += $3 } END { print x }'。这可能比Python的同等操作要快3倍,而且要短3倍。在一个或多个文件中,替换所有出现在特定地方的某个字符串:
perl -pi.bak -e 's/old-string/new-string/g' my-files-*.txt要立即根据某个模式对大量文件重命名,使用
rename。对于复杂的重命名,repren可以帮助你达成。# 恢复备份文件 foo.bak -> foo: rename 's/\.bak$//' *.bak # 完整的文件名、目录名 foo -> bar: repren --full --preserve-case --from foo --to bar .使用
shuf来从某个文件中打乱或随机选择行。了解
sort的选项。知道这些键是怎么工作的(-t和-k)。特别是,注意你需要写-k1,1来只通过第一个字段排序;-k1意味着根据整行排序。稳定排序(
sort -s)会很有用。例如,要首先按字段2排序,然后再按字段1排序,你可以使用sort -k1,1 | sort -s -k2,2如果你曾经需要在
Bash命令行中写一个水平制表符(如,用于-t参数的排序),按ctrl-v [Tab],或者写$'\t'(后面的更好,因为你可以复制/粘贴)。对源代码进行补丁的标准工具是
diff和patch。 用diffstat来统计 diff 情况。注意diff -r可以用于整个目录,所以可以用diff -r tree1 tree2 | diffstat来统计(两个目录的)差异。对于二进制文件,使用
hd进行简单十六进制转储,以及bvi用于二进制编辑。还是用于二进制文件,
strings(加上grep等)可以让你找出一点文本。对于二进制文件的差异(
delta压缩),可以使用xdelta3。要转换文本编码,试试
iconv吧,或者对于更高级的用途使用uconv;它支持一些高级的Unicode的东西。例如,这个命令可以转换为小写并移除所有重音符号(通过扩展和丢弃):uconv -f utf-8 -t utf-8 -x '::Any-Lower; ::Any-NFD; [:Nonspacing Mark:] >; ::Any-NFC; ' < input.txt > output.txt要将文件分割成几个部分,来看看
split(按大小分割)和csplit(按格式分割)吧。使用
zless,zmore,zcat和zgrep来操作压缩文件。
系统调试
对于
Web调试,curl和curl -I很方便灵活,或者也可以使用它们的同行wget,或者更现代的httpie。要了解磁盘、
CPU、网络的状态,使用iostat,netstat,top(或更好的htop)和(特别是)dstat。它们对于快速获知系统中发生的状况很好用。对于更深层次的系统总览,可以使用
glances。它会在一个终端窗口中为你呈现几个系统层次的统计数据,对于快速检查各个子系统很有帮助。要了解内存状态,可以运行
free和vmstat,看懂它们的输出结果吧。特别是,要知道cached值是Linux内核为文件缓存所占有的内存,因此,要有效地统计free值。Java系统调试是一件截然不同的事,但是对于Oracle系统以及其它一些JVM而言,不过是一个简单的小把戏,你可以运行kill -3 <pid>,然后一个完整的堆栈追踪和内存堆的摘要(包括常规的垃圾收集细节,这很有用)将被转储到stderr/logs。使用
mtr作路由追踪更好,可以识别网络问题。对于查看磁盘满载的原因,
ncdu会比常规命令如du -sh *更节省时间。要查找占用带宽的套接字和进程,试试
iftop或nethogs吧。(
Apache附带的)ab工具对于临时应急检查网络服务器性能很有帮助。对于更复杂的负载测试,可以试试siege。对于更仔细的网络调试,可以用
wireshark,tshark或ngrep。掌握
strace和ltrace。如果某个程序失败、挂起或崩溃,而你又不知道原因,或者如果你想要获得性能的大概信息,这些工具会很有帮助。注意,分析选项(-c)和使用-p关联运行进程。掌握
ldd来查看共享库等。知道如何使用
gdb来连接到一个运行着的进程并获取其堆栈追踪信息。使用
/proc。当调试当前的问题时,它有时候出奇地有帮助。样例:/proc/cpuinfo,/proc/xxx/cwd,/proc/xxx/exe,/proc/xxx/fd/,/proc/xxx/smaps。当调试过去某个东西为何出错时,
sar会非常有帮助。它显示了CPU、内存、网络等的历史统计数据。对于更深层的系统和性能分析,看看
stap(SystemTap),perf和sysdig吧。确认是正在使用的
Linux发行版版本(支持大多数发行版):lsb_release -a。每当某个东西的行为异常时(可能是硬件或者驱动器问题),使用
dmesg。
单行程序
这是将命令连成一行的一些样例:
有时候通过
sort/uniq对文本文件做交集、并集和差集运算时,这个例子会相当有帮助。假定a和b是已经进行了唯一性处理的文本文件。这会很快,而且可以处理任意大小的文件,总计可达数千兆字节。(Sort不受内存限制,不过如果/tmp放在一个很小的根分区的话,你可能需要使用-T选项。)也可参见上面关于LC_ALL的注解和-u选项(参见下面例子更清晰)。sh cat a b | sort | uniq > c # c 是 a 和 b 的并集 cat a b | sort | uniq -d > c # c 是 a 和 b 的交集 cat a b b | sort | uniq -u > c # c 是 a 减去 b 的差集使用
grep . *来可视化查看一个目录中的所有文件的所有内容,例如,对于放满配置文件的目录:/sys,/proc,/etc。对某个文本文件的第三列中所有数据进行求和(该例子可能比同等功能的
Python要快3倍,而且代码也少于其3倍):awk '{ x += $3 } END { print x }' myfile如果想要查看某个文件树的大小
/日期,该例子就像一个递归ls -l,但是比ls -lR要更容易读懂:find . -type f -ls只要可以,请使用
xargs或parallel。注意,你可以控制每行(-L)执行多少个项目,以及并行执行(-P)。如果你不确定它是否会做正确的事情,可以首先使用xargs echo。同时,使用-I{}也很方便。样例:find . -name '*.py' | xargs grep some_function cat hosts | xargs -I{} ssh root@{} hostname比如说,你有一个文本文件,如
Web服务器的日志,在某些行中出现了某个特定的值,如URL中出现的acct_id参数。如果你想要统计有多少个acct_id的请求:cat access.log | egrep -o 'acct_id=[0-9]+' | cut -d= -f2 | sort | uniq -c | sort -rn
命令总结
expr:实施算术或布林操作,或者求正则表达式的值m4:简单的宏处理器yes:大量打印一个字符串cal:漂亮的日历env:(以特定的环境变量设置)运行一个命令(脚本中很有用)look:查找以某个字符串开头的英文单词(或文件中的行)cut和paste以及join:数据处理fmt:格式化文本段落pr:格式化文本为页/列fold:文本折行column:格式化文本为列或表expand和unexpand:在制表符和空格间转换nl:添加行号seq:打印数字bc:计算器factor:分解质因子gpg:加密并为文件签名toe:terminfo条目表nc:网络调试和数据传输socat:套接字中继和tcp端口转发(类似netcat)slurm:网络流量可视化dd:在文件或设备间移动数据file:识别文件类型tree:以树形显示目录及子目录;类似ls,但是是递归的stat:文件信息tac:逆序打印文件shuf:从文件中随机选择行comm:逐行对比分类排序的文件hd和bvi:转储或编辑二进制文件strings:从二进制文件提取文本tr:字符转译或处理iconv或uconv:文本编码转换split和csplit:分割文件units:单位转换和计算7z:高比率文件压缩ldd:动态库信息nm:目标文件的符号ab:Web服务器基准测试strace:系统调用调试mtr:用于网络调试的更好的路由追踪软件cssh:可视化并发shellrsync:通过SSH同步文件和文件夹wireshark和tshark:抓包和网络调试ngrep:从网络层摘取信息host和dig:DNS查询lsof:处理文件描述符和套接字信息dstat:有用的系统统计数据glances:高级,多个子系统概览iostat:CPU和磁盘使用率统计htop:top的改进版last:登录历史w:谁登录进来了id:用户/组身份信息sar:历史系统统计数据iftop或nethogs:按套接口或进程的网络使用率ss:套接口统计数据dmesg:启动和系统错误信息hdparm:SATA/ATA磁盘操作/改善性能lsb_release:Linux发行版信息lsblk:列出块设备,以树形展示你的磁盘和分区lshw:硬件信息