其中一个有趣的现象是:对于别名,它会告诉你某个别名将被解析到何处。例如,在 Bash 和 Zsh 中, ll
显示为一个别名,而在 Fish 中,由于 ll
是默认提供的,所以它会告诉你这是内置的 Shell 功能。Linux 中的 which
命令
假定你有一个可直接执行的命令,因为它处在 Shell 路径中,但你想知道它的具体位置。
你可以用 which
来做这件事。这个命令会返回指定命令的路径。
which
只对存储在磁盘上的可执行文件起作用,对别名或内置 Shell 功能无效。Linux 中的 nohup
命令
有时你必须在远程机器上运行一个长时间活跃的进程,但之后你需要断开连接。
或者,你只是想防止当本地和服务器之间有任何网络问题时,命令被停止执行。
要让任一命令在登出或关闭服务器会话后继续运行,可以使用 nohup
命令。
执行 nohup <命令>
可以让某个进程在你登出后继续工作。
Linux 中的 xargs
命令
在 UNIX Shell 中,xargs
命令用来将标准输入的数据转换成命令的参数。
换句话说,使用 xargs
,可以将一条命令的输出,用作另一条命令的输入。
下面是你将会用到的语法:
command1 | xargs command2
我们使用管道符(|
)将输出传递给 xargs
。它将负责运行 command2
命令,使用 command1
的输出作为参数。
我们来做个简单的例子。假设你要删除某个目录下的一些特定文件。这些文件列在一个文本文件中。
我们有三个文件:file1
、 file2
、 file3
。
在 todelete.txt
中,我们有一份想要删除的文件列表,在这一例子中是 file1
和 file3
:
我们将通过 xargs
把 cat todelete.txt
的输出引向 rm
命令。
就像这样:
cat todelete.txt | xargs rm
以下是执行结果,我们列出的文件现在已经被删除:
它的工作方式是:xargs
会运行 rm
2次,为 cat
返回的每一行运行一次。
这是 xargs
最简单的用法。我们还可以使用以下的一些参数。
在我看来,其中最有用的是 -p
(特别是刚开始学习 xargs
时)。使用这个选项将使 xargs
打印出一个确认提示,说明它要采取的行动:
-n
选项令 xargs
每次执行若干个迭代,因此你可以用 -p
单独确认它们。这里我们用 -n1
告诉 xargs
一次执行一个迭代:
另一个广泛应用的参数是 -I
。它可以将输出内容放入占位符,之后你可以用来做各种事。
其中一件事是同时运行多个命令,例如:
command1 | xargs -I % /bin/bash -c 'command2 %; command3 %'
你可以将上方的 %
符号换成其他任何东西——它只是个变量。
Linux 中的 vim
编辑器命令
vim
是一个非常流行的文件编辑器,特别是在程序员中。它被积极开发且经常更新,且有巨大的社区力量围绕着。甚至还有一个 Vim 会议!
在现代系统中,vi
只是 vim
的一个别名,意思是“改进的 vi
”(即 “vi
im
proved”)。
你可以在命令行运行 vi
启动它。
调用时指定一个文件名,你就可以编辑对应的文件:
vi test.txt
你需要了解的是,Vim 有两个主要的模式:
- 命令(command) 模式,也称为 普通(normal) 模式
当你启动编辑器时,默认处于命令模式。这时你无法像期望的那样,在基于图形界面的编辑器中输入文本。你需要进入插入模式。
可以按下 i
键进入插入模式。当你这样做之后, 在编辑器下方会出现 -- 插入 --
(或 INSERT)字样:
现在你可以开始输入了,用文件内容来填充终端屏幕:
你可以用方向键在文件中移动光标,或者使用 h
- j
- k
- l
四个键。h-l
代表左和右,j-k
代表上和下。
当完成编辑时,按下 esc
键即可退出插入模式,回到命令模式。
此时你可以浏览文件,但无法向其添加内容(要注意按下了哪个键,某些键可能是编辑器的命令)。现在你可能想知道如何保存文件。可以按下 :
(冒号),然后输入 w
,即 :w
要保存并退出,可以按下 :
然后输入 w
和 q
,即 :wq
要退出但不保存文件,可以按下 :
然后输入 q
和 !
,即 :q!
要撤销某一个更改并再次编辑,可以在命令模式中按下 u
。如果要重做 (取消上次的撤销操作),可以按下 ctrl-r
。
以上是使用 Vim 工作的基本操作。接下来是一个无底洞,这篇简短的介绍是无法讲完的。
下面我只会提到那些能让你入门 Vim 编辑的命令:
- 定位到任一单词的首字母,按下
d
,然后按 w
即可删除相应单词。如果输入 e
而非 w
,后一个单词前的空白处将被保留 - 在
d
和 w
之间加入一个数字,即可删除多个单词,例如使用 d3w
来向前删除 3 个单词 - 按下
d
然后再按一次 d
,即可删除整行。按下 d
然后再按 $
,即可删除以光标为开头,直至当前行末尾的整行内容。
如需了解更多 Vim 的内容,我推荐参阅 Vim 常见问题。你还可以运行 vimtutor
命令,它应该已经安装到系统中,可以对你开始探索 vim
有很大帮助。
Linux 中的 emacs
编辑器命令
emacs
是一个很棒的编辑器,它在历史上被认作是专为 UNIX 系统而生的。更著名的是:围绕 vi
与 emacs
之间的火热纷争与激烈论战曾给全世界的开发者带来许多无益的时光。
emacs
非常强大。一些人将其当作一种操作系统,全天候都在使用它 (https://news./item?id=19127258)。我们在此处只谈及一些基础的用法。
你可以调用 emacs
来开启新的 emacs 会话:
macOS 用户们,现在请停一下。如果你当前在使用 Linux,那就没有什么问题,但 macOS 并未搭载使用 GPLv3 协议的应用程序,且每个内置的 UNIX 命令也没有更新到 GPLv3 版本。
虽然这对于我以上已经列出的命令来说,只是个小问题,但就本例而言,使用 2007 年的 emacs 版本与使用经过十余年改进和变化的版本,体验并不完全相同。
对于时常更新的 Vim 来说,这也不算什么。但想要解决 emacs 的问题,你需要运行 brew install emacs
,之后再运行 emacs
,即可使用 Homebrew 提供的新版本(确保 Homebrew 已安装)。
与 Vim 类似,你也可以调用 emacs <文件名>
来编辑已有的文件:
现在你可以开始编辑。当你完成编辑,先按下 ctrl-x
,然后按下 ctrl-w
。先确认文件夹:
而 Emacs 会告诉你这个文件已存在,并询问是否要覆盖它:
回答 y
,你会得到一条操作成功的确认信息:
要退出 Emacs ,可以按下 ctrl-x
,然后再按 ctrl-c
。或者先按下 ctrl-x
之后再按 c
(期间按住 ctrl
不放)。Emacs 还有很多要了解的地方,限于篇幅,我在这篇简短教程中不便展开。我鼓励诸位按下 ctrl-h
r
打开内置参考手册,或按下 ctrl-h
t
打开官方教程以继续学习。
Linux 中的 nano
编辑器命令
nano
是一个对初学者友好的编辑器。
输入 nano <文件名>
即可运行。
你可以直接向文件中输入字符,而不必担心所在的模式。
想退出而不修改,你可以直接按下 ctrl-X
。如果你已经编辑了文件缓冲区,编辑器会弹出确认提示,你可以选择保存或放弃更改。
底部的帮助栏为你显示了一部分用于处理文件的键盘命令:
另一条命令 pico
与它大致相同,不过 nano
其实是 pico
的 GNU 版本,后者在一段历史时期内并未开源。于是人们克隆出 nano
以满足 GNU 操作系统的许可要求。Linux 中的 whoami
命令
键入 whoami
即可将当前登录终端会话的用户名打印出来:
注意:这和可以输出更多信息的 who am i
命令并不一样。
Linux 中的 who
命令
who
命令显示当前已登录系统的用户。
除非你在使用多人访问的服务器,否则你可能是唯一的登录用户,并且登录了多次:
为什么说是多次呢?因为每打开一次 Shell,都会被算作一次访问。
你可以在此看到使用的终端名,以及会话的起始时间/日期。
参数 -aH
将使 who
显示更多的信息,包括空载的时间与终端的进程 ID:
特殊的 who am i
命令会列出当前终端会话的详情:
Linux 中的 su
命令
当你用一个用户登录到终端 Shell 时,可能需要切换到另一个用户。
例如,你以 root 身份登录,进行了维护工作,但之后你想切换到别的用户账户。
你可以用 su
命令来完成:
su <用户名>
例如:su flavio
.
如果你以用户身份登录,且不带参数运行 su
命令,它会遵从默认行为——提示你输入 root
用户的密码。
su
会以另一个用户的身份,开启新的 Shell。当你完成操作,执行 exit
即可关闭新开的 Shell,并回到当前用户的 Shell。
Linux 中的 sudo
命令
sudo
通常用来以 root 身份运行命令。
你必须先启用当前身份才能使用 sudo
,启用之后,你可以直接输入你自己的登录密码( 而非 root 用户的密码)来以 root 身份运行命令。
这种权限是高度可配置的,在多用户的服务器环境中尤其有用。一些用户可以通过 sudo
被授予运行特定命令的权限。
例如,你可以用它编辑任一系统配置文件:
sudo nano /etc/hosts
这在普通模式下是无法实现的,因为你没有相应的权限。
你可以执行 sudo -i
,以 root 身份启动一个 Shell:
还可以使用 sudo
以其他任何用户身份运行命令。默认情况是 root
, 但加上 -u
参数即可指定使用其他用户:
sudo -u flavio ls /Users/flavio
Linux 中的 passwd
命令
在 Linux 中,用户都有一个指定的密码。你可以使用 passwd
命令修改这个密码。
这里有两种情况。
第一种情况是:你想要修改自己的密码,此时你可以输入:
passwd
交互式提示会先询问你的旧密码,之后要求你输入新密码:
当你处于 root
身份(或是其他具有超级用户权限的用户)时,你可以设置你想要更改密码的用户名:
passwd <username> <new password>
此时你无需输入旧密码。
Linux 中的 ping
命令
ping
命令可以在本地网络或互联网上探测一个特定的网络主机。
它的语法是 ping <host>
,其中 <host>
可以是域名或 IP 地址。
以下是探测 google.com
的例子:
这个命令向服务器发送一个请求,服务器则返回其响应信息。ping
在默认情况下,每秒持续发送请求,只有按下 ctrl-C
时才会停止。你可以用 -c
参数指定想要的尝试次数:ping -c 2 google.com
。
一旦 ping
结束运行,它将输出一些结果:例如数据包丢失的百分比,以及其他关于网络性能的统计数据。
你可以看到,屏幕上输出了主机的 IP 地址,以及得到响应所花的时间。
并不是所有的服务器都可以探测,此时会出现请求超时:
有时这是为了“隐藏”服务器,或是减低服务器负载而故意设置的。为了探测所发送的数据包也可以被防火墙过滤。
ping
使用 ICMP 协议 (全称 Internet Control Message Protocol ,互联网控制报文协议)工作。ICMP 与 TCP 和 UDP 一样,是网络层协议。
探测请求向服务器发送一个含有 ECHO_REQUEST
信息的数据包,服务器则会返回 ECHO_REPLY
信息。此处我将不展开讲述,但这是最基本的概念。
用 Ping 探测,在测试主机是否可以访问时非常有用(此处假设主机支持探测),还可以从主机返回信息的时长,获知它的距离有多远。
通常,服务器在地理上离你越近,它向你返回信息的时间就越短。简单的物理规律则告诉我们:电缆越长,数据延迟越高。
Linux 中的 traceroute
命令
当你想要在互联网上到访某个主机时,数据首先会经过家庭路由器,然后到达你的运营商网络,再穿过上层的网络路由器,以此类推,直到最终连通主机。
你是否曾想过:数据包需要经过哪些步骤才能做到这一点?
traceroute
命令就是为此而生的。
你可以调用
traceroute <host>
它将会(缓慢地)在数据包旅行时收集所有相关信息。
以下的例子中,我将尝试用 traceroute flaviocopes.com
到访我的博客:
通常,我们可以看到主机名、IP 地址以及一些性能指标。但并不是所有经过的路由器都会向我们返回信息,此时,traceroute
会输出 * * *
。
每个路由器都可以看到 3 个样本,这意味着 traceroute 默认尝试了 3 次,让你很好地了解到达主机所需的时间。
这就是对服务器执行 traceroute
比简单地执行 ping
要花更多时间的原因。
你可以用 -q
参数自定义尝试的次数:
traceroute -q 1 flaviocopes.com
Linux 中的 clear
命令
输入 clear
来清除当前终端之前执行的所有命令。
此时屏幕会被清理,你将只看到顶部的提示:
提示:这个命令有个好用的快捷键:ctrl-L
不过,一旦使用了这个命令,你将不能用鼠标滚轮查看此前输入的命令。
因此你可能更想使用 clear -x
,这个参数可以在清理屏幕的同时,保留之前的终端输入,向上滚动鼠标即可回溯查看。
Linux 中的 history
命令
每次运行命令,都会在历史中保存一条记录。
你可以输入下面的命令来查看所有历史记录:
history
这会显示带有序号的历史记录:
你可以使用 !<命令序号>
重现已经储存在历史记录中的命令。以上的例子中,输入 !121
会重现 ls -al | wc -l
命令。
通常,历史记录会保留最后执行的 500 条命令。
你可以将这个命令与 grep
结合使用,以找到之前运行的命令:
history | grep docker
如果要清除历史记录,运行 history -c
即可。Linux 中的 export
命令
export
命令用来向子进程输出变量。
这是什么意思呢?
假设你像下面这样定义一个 TEST 变量:
TEST='test'
你可以用 echo $TEST
输出它的值:
但如果你尝试用以上命令,定义一个名为 script.sh
的 Bash 脚本:
然后设定 chmod u+x script.sh
,并输入 ./script.sh
执行脚本。此时,再执行 echo $TEST
将不会输出任何内容!
这是因为在 Bash 中,TEST
被定义为局部变量。当执行一个 Shell 脚本或其他命令时,Bash 会为其单独启动一个子 Shell,这个子 Shell 不会包含当前 Shell 的局部变量。
如果想让变量在子 Shell 中仍然起作用,则不能使用以下命令定义 TEST
:
TEST='test'
而是要这样:
export TEST='test'
尝试以上命令,然后执行 ./script.sh
,现在 'test' 应该可以输出了:
有时你需要在变量上附加一些内容。这常用于 PATH
变量。此时就需要像下面这样:export PATH=$PATH:/new/path
当你在终端中直接建立新变量时,通常会使用 export
。此外,当你在 Bash 的 .bash_profile
或 .bashrc
配置文件,或 Zsh 的 .zshenv
配置文件中定义变量时,也可以使用它
要想删除一个变量,使用 -n
参数即可:
export -n TEST
不带参数调用 export
,会列举当前已经输出的所有变量。
Linux 中的 crontab
命令
Cron 作业通常指定期运行的作业。凭借它们,你可以让任一命令在每小时、每天、每两周或是周末执行。
它们非常强大,特别是在服务器上执行维护或自动化任务时。
crontab
命令是处理 Cron 作业的入口。
你能够做的第一件事是探索你定义了哪些 Cron 作业:
crontab -l
此处你可能像我一样,什么都没见到:
运行
crontab -e
来编辑已有的 Cron 作业,或是添加新的作业。
默认情况下,它会用系统默认编辑器(通常是 vim
)打开。我更喜欢 nano
。你可以用下面这条命令切换不同的编辑器:
EDITOR=nano crontab -e
现在,你可以为每个 Cron 作业添加一行配置。
定义作业的语法有些吓人。因此我常用一个网站来帮助我生成配置而不出错:https:///
此处,你为 Cron 作业选择一个时间间隔,之后输入要执行的命令。
我选择每 12 小时运行来自 /Users/flavio/test.sh
的脚本。以下是我需要执行的 crontab 配置行:
* */12 * * * /Users/flavio/test.sh >/dev/null 2>&1
我运行 crontab -e
:
EDITOR=nano crontab -e
然后添加以上配置行,之后按下 ctrl-X
然后再按 y
保存。
如果一切顺利,那么 Cron 作业就设置好了:
一旦完成,你可以运行以下命令查看当前激活的 Cron 作业列表:
crontab -l
要删除 Cron 作业,只需再一次运行 crontab -e
,删除相应配置行,保存并退出编辑器即可。
Linux 中的 uname
命令
不带任何参数执行 uname
将会返回当前操作系统的代号:
参数 m
可以显示硬件名称(本例中为 x86_64
),而参数 p
会输出处理器架构名称(本例中为 i386
):
参数 s
输出操作系统名称,参数 r
输出当前发布版本的名称,而参数 v
输出版本号:
参数 n
输出网络节点,也就是当前主机的名称:
参数 a
则会输出所有可用的信息:
在 macOS 上,你还可以使用 sw_vers
命令,输出更多关于操作系统的信息。注意这和上方 Darwin (内核)的版本 19.6.0
不同。
Darwin 是 macOS 内核的名称。内核是操作系统的“核心”,而操作系统作为一个整体称为 macOS。在 Linux 中,Linux 是内核名称,而 GNU/Linux 才是操作系统名称(尽管我们会习惯性称其为 'Linux')。
Linux 中的 env
命令
env
命令可以用来传递环境变量,而不需要在外部环境(例如当前 Shell 中)设置它们。
假设你想运行一个 Node.js 应用,同时要为它设置名为 USER
的变量。
你可以运行
env USER=flavio node app.js
此时,Node.js 应用可以通过 Node 的 process.env
接口访问 USER
这个环境变量。
你也可以通过附加 -i
参数,清除所有已经设置的环境变量:
env -i node app.js
这种情况下,你有可能得到一个错误提示 env: “node”: 没有那个文件或目录
,这是由于 Shell 用来查找共用命令路径的 PATH
变量已被卸除,导致 node
命令无法找到。
因此你需要把完整的路径传递给 node
程序:
env -i /usr/local/bin/node app.js
我们用带有以下内容的 app.js
文件来试试:
console.log(process.env.NAME)
console.log(process.env.PATH)
你将会看到这样的输出:
undefined
此时你可以传递一个 env 变量:
env -i NAME=flavio node app.js
然后输出会变成:
flavio
undefined
去掉 -i
参数会让 PATH
变量在应用中再次可用:
如果不带参数运行 env
命令,它还可以用来列出所有环境变量:
env
它会返回已设置的环境变量的列表,例如:
HOME=/Users/flavio
LOGNAME=flavio
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin
PWD=/Users/flavio
SHELL=/usr/local/bin/fish
你还可以使用 -u
参数,即可让某个变量在你运行的应用中无法访问。例如,下面的命令移除了当前环境中的 HOME
变量:
env -u HOME node app.js
Linux 中的 printenv
命令
以下是 printenv
命令的快速指南,他可以用来输出环境变量对应的值。
任何 Shell 中都有大量的环境变量,有的是系统设置的,有的是你自己的 Shell 脚本或配置所产生的。
你可以使用 printenv
命令,将它们全部打印到终端中。输出大概就像下面这样:
HOME=/Users/flavio
LOGNAME=flavio
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin
PWD=/Users/flavio
SHELL=/usr/local/bin/fish
通常还会多几行。
你可以传递一个变量名作为参数,只显示指定变量的值:
printenv PATH
结语
感谢你阅读这份命令指南。
我希望它会激发你去学习更多关于 Linux 及其能力的知识。这些知识就像是一棵常青树,不会很快过时。
请记住,如果你愿意,随时可以免费下载这本书的 PDF、ePUB、Mobi 版本!
如果想查看更多类似的精彩内容,我每天会在我的网站 flaviocopes.com 上发布编程教程。
原文链接:https://www./news/the-linux-commands-handbook/