Linux Command Handbook Translation
最近拜读了Flavio大佬的Linux简书《The Linux Commands Handbook》,并抽时间将其翻译成中文版,大家如果有需要,可以私信我获取书籍pdf,免费分享。现将鄙人翻译的成品展现给大家,译者水平有限,若有不理解的地方可以私信我,我们一起来探讨相关技术。
下面开始书籍正文:
这里呈现的所有命令都可以在任何由Unix环境的系统中使用,比如在Linux、MacOS、WSL上。
Linux以及shells介绍
Linux是一个类似于Windows或MacOS一样的操作系统。它也是目前世界上最受欢迎的开源、免费且自由使用的操作系统。Linux系统赋能了众多组成互联网的服务端。它是一切事物建立的基础。但是不止于此,安卓(修改后的版本)也是基于Linux建立起来的。
man Command
第一个想要介绍的命令是一个可以帮助你理解所有其他命令的命令。每次挡你不知道如何使用一个命令的时候,只需要使用下面的命令获取操作方法即可:
man <command>
这个命令会给出你一个手册页,手册页对一个开发者来说是一个非常重要的学习工具。这里会包括了非常多的信息以至于你会发现有时候这些信息太多了。
大多数时候我们只需要快速地掌握一个命令的简单用法就可以了,因此这里推荐一个tldr
命令的网站:https://tldr.sh/。对于这个命令,在大多数客户端都是Node.js
环境的情况下,你可以使用命令
npm install -g tldr
来安装tldr
这个命令。等待npm
安装好tldr
命令之后,就可以使用类似于tldr <command>
这样的命令语法正常使用了。比如使用
tldr ls
需要注意的是这个命令并不是对于man
命令的一个替代方案,但是却是一个非常方便的工具,帮你避免迷失在由man page
中展示的庞大信息中。随后你就可以使用man page
手册页来探寻所有其他你可以在一个命令中使用的不同选项以及参数。
ls
在一个文件夹中,你可以使用ls
命令来展示这个文件夹中所有文件,首先来看一下这个该命令的简单使用方法。
这个命令较为简单,在ls
之后可以添加文件夹的名称或目录,然后它将会打印出该文件夹的目录文件。ls
命令接收很多的选项options
,其中一个我最喜欢的选项结合就是-al
让我们来试一试:
ls -al ./
该命令与平常ls
命令的区别就是会展示更多的信息。那么从左到右每一列分别表示什么意思?
- 文件权限(如果你的系统支持ACLs,你也可以得到一个ACL标识)
- 链接到该文件的数量??
- 文件的所有者
- 文件的组别
- 文件的字节大小
- 文件最后一次修改时间(单位是什么?)
- 文件名称
这里可以简单了解一下,展示详细信息的选项是-l
在起作用,-a
选项的作用是展示一些隐藏的文件(就是以.
开头的文件)。=500x
cd
这个命令用于控制终端进入到指定的目录中,改变当前工作目录
一些简单的用法可以参考上面所展示的内容。
pwd
每当你感觉到已经在文件系统中迷失了的话,就可以使用该命令来打印出当前的工作路径。
mkdir
你可以使用mkdir
命令来创建一个文件夹,后面的选项是你要创建的文件夹名称,不仅可以接收一个文件夹名称,也可以接收多个参数,用于创建多个不同的文件夹。
mkdir fruits
以上命令会在当前目录下创建一个叫做fruits
的文件,再比如
mkdir dogs cars
这个命令接收了多个参数,用于在当前目录下创建dogs
和cars
两个文件夹。
需要注意的是,除了可以创建单个空文件夹,该命令也可以创建嵌套的文件夹,这时就需要使用到-p
选项,如下指令
mkdir -p fruits/apples
于是该命令就可以在fruits
文件夹下再创建一个apples
文件夹,提醒一下这里想要使用-p
选项创建嵌套文件夹的时候,可以在第一个根目录不存在的情况下使用,这样的话就会新建一个你传入的文件夹。
除了-p
选项,mkdir
命令还有其他的一些选项,比如-m
用于创建固定权限的文件夹,其他的一些选项可以使用手册页面命令查看
man mkdir
刚发现原来可以综合使用这些功能,比如下面的命令
mkdir dogs cars -p fruits/apples
rmdir
正如你可以使用mkdir
命令来创建一个空的文件夹,你也可以使用rmdir
命令用来删除一个空文件夹,需要注意的是只能删除空文件夹
mkdir fruits
rmdir fruits
你也可以同时删除多个空的文件夹
mkdir fruits cars
rmdir fruits cars
你要删除的文件夹必须是没有包含任何文件的,也就是说必须是空的文件夹。如果你想要删除有内容的文件夹,我们将会使用到更加简洁的rm
命令,也会紧接着使用-rf
选项来强制删除一个非空的文件夹。
mkdir -p fruits/apples
rm -rf fruits
需要小心一点这个命令选项不会询问你是否确定要删除该文件夹,并且它会立即删除你要删除的任何东西。而且当你使用这个命令删除文件的时候是不会将其放入回收箱中的,因此恢复这些丢失的文件是非常困难的。
mv
一旦你有了一個文件,你就可以使用mv
命令將它隨意移動。只需要確認這個文件當前的路徑以及它的新路徑。简单的介绍可以查看下面的介绍
也就是说该命令的作用是移动或重命名一个文件及文件夹。
- 如果目标文件是一个不存在的目录或文件,则会重命名
比如最开始使用ls -l
命令查看一下当前工作目录下的文件,如下
total 4
-rw-r--r-- 1 gitpod gitpod 0 Sep 10 12:15 index.css
-rw-r--r-- 1 gitpod gitpod 0 Sep 9 01:16 index.html
-rw-r--r-- 1 gitpod gitpod 12 Sep 9 02:17 index.js
drwxr-xr-x 3 gitpod gitpod 18 Sep 10 12:21 mvdir
-rw-r--r-- 1 gitpod gitpod 0 Sep 10 12:13 yarn.lock
然后使用重命名或移动命令
mv yarn.lock renameyarn.lock
那么再次使用ls -l
命令查看一下当前工作目录下的文件,就变成了如下样子
total 4
-rw-r--r-- 1 gitpod gitpod 0 Sep 10 12:15 index.css
-rw-r--r-- 1 gitpod gitpod 0 Sep 9 01:16 index.html
-rw-r--r-- 1 gitpod gitpod 12 Sep 9 02:17 index.js
drwxr-xr-x 3 gitpod gitpod 18 Sep 10 12:21 mvdir
-rw-r--r-- 1 gitpod gitpod 0 Sep 10 12:13 renameyarn.lock
于是就把文件yarn.lock
重命名为了renameyarn.lock
文件
- 如果目标文件名称是一个存在的目录,那么就会将前几个文件移动到该文件夹下
touch file1
touch file2
mkdir testdir
mv file1 file2 ./testdir
很明显,上面的指令就会将新建的file1
和file2
两个文件移动到testdir
文件夹之下,同理这里可以移动的文件个数不只有两个。
cp
该命令用来复制并粘贴一个文件或文件夹,对于文件的复制直接在该命令之后加上源文件名称以及要复制过去的文件名字即可。
cp index.js indexcopy.js
如上命令就会在本工作目录下创建一个与index.js
文件一模一样的indexcopy.js
文件。如果想要复制一个文件夹,需要使用-r
选项,该选项的意思是递归复制整个文件夹目录。
mkdir drugs
cp -r drugs drugscopy
这样就会将上一个文件夹中的文件原封不动地复制粘贴到新的文件夹中。
open
本open
命令会使你用下面的语法打开一个文件
open <filename>
你也可以打开一个文件夹目录,该操作在MacOS
系统上会将当前的工作目录在访达软件中打开。
open <directory name>
以后在使用mac
系统的时候,有可能会经常使用open .
命令来打开当前的目录。
需要注意的是 . 标识 指的是当前目录,而 … 标识指的是上一级目录
同样的命令也可以被使用在打开一个应用的时候
open <application name>
touch
你可以使用touch
命令创建一个新的文件,而且如果这个文件已经存在了,那么该命令将会以写的模式打开该文件,并会更新它的时间戳。
ln
ln
命令是Linux
文件系统命令的一部分,它被用来创建链接,那么什么是链接呢?它就像是一个指向另一个文件的指针。也可以理解为一个文件,该文件指向了另一个文件。你可能会熟悉Windows
中的快捷方式,他们是类似的。我们在linux
系统中有两种类型的链接:硬链接
(Hard Links
)和软链接
(Soft Links
)。
- 硬链接(Hard links)
我们一般很少使用硬链接。硬链接有许多的限制,比如你不能链接到一个文件夹目录,也不能链接到外部的文件系统(磁盘)。
要创建一个硬链接可以使用命令
ln <original> <link>
举个例子,如果你有一个叫做recipes.txt
的文件,你可以给它创建一个硬链接通过使用命令
ln recipes.txt newrecipes.txt
你创建的硬链接和一个常规的文件并没有什么区别。而且这两个文件具有非常强烈的关联性,也就是说当其中任何一个文件发生变化的时候,其他一个文件内容也会跟着更新。
如果你删除了源文件,这个链接将仍然保留源文件的内容,因为在有一个硬链接指向它之前是不会被清除的。
- 软链接(Soft Links)
软链接就不同了,它的功能更加强大因为你可以直接链接到其他的文件系统以及文件夹中,但是当源文件被移除的时候,这个软链接也就随即受到破坏了。为了创建一个软链接,你可以使用ln
命令的-s
选项。
ln -s <original> <link>
例如,你现在有一个叫做recipes.txt
的文件,可以使用以下命令创建一个软链接:
ln -s recipes.txt newrecipes.txt
好的,现在让我们来看一下创建了一个软链接之后,文件会发生什么变化,下面的截图展示的是在我们创建了一个软链接之后新的软连接发生了什么变化。
从上面的命令中可以看出来,当我们创建了一个软链接之后,展示文件详细信息的时候新建的软链接文件newrecipes.txt
会有一个箭头指向recipes.txt
文件,代表它的内容最终是指向源文件recipes.txt
的,而且你也会看到在文件的开头有一个l
的标识。
现在如果删除掉源文件,那么这个软链接就失效了,并且当你尝试去访问这个软链接文件的时候,控制台就会告诉你No such file or directory
。
gzip
你可以使用gzip
压缩命令通过叫做LZ77
的gzip
压缩协议来压缩一个文件,最简单的一个例子如下:
gzip filename
这个命令将会压缩该文件,并且会在该文件的后面加上.gz
后缀,然后将源文件删除。为了防止其删除源文件,你可以使用-c
选项并且使用**输出重定向(Output Redirection)**来将输出写到filename.gz
文件中:
gzip -c filename > filename.gz
这里的-c
选项特别标识出输出将会走标准输出流,并保证源文件保持完好无损(intact)。或者你也可以是使用-k
选项:
gzip -k filename
对于打包会有各种各样的等级。打包的文件越多,解压或打包的时间就会越长。打包等级范围从1(速度最快、质量最差打包)到9(速度最慢、质量更好打包),需要知道的是默认打包等级是6。
通过使用-<NUMBER>
选项,你可以选择特定的打包等级:
gzip -6 filename
你也可以通过列举一系列的文件名称来打包多个文件:
gzip filename1 filename2
你可以使用递归的形式打包整个目录文件夹中的所有文件,可以使用-r
选项。
gzip -r a_folder
再介绍一个选项-v
,它会打印出打包的百分比信息,这里有一个关于它与选项-k
一起使用的例子:
gzip -kv wget-log
gzip
命令也可以被用来解压一个文件,通过使用-d
选项:
gzip -d filename.gz
gunzip
gunzip
命令和gzip
命令基本是等效的,除了一点就是在gunzip
命令中,-d
选项总是默认启用的。这个命令可以通过下面的方式触发:
gunzip filename.gz
这个命令将会解压filename.gz
文件并且会移除掉.gz
扩展名,将解压后的结果放到filename
文件中。如果这个文件已经存在了,那么就会重写它。你也可以通过使用-c
选项将输出结果重定向到一个不同的文件名中:
gunzip -c filename.gz > anotherfilename
tar
tar
命令是被用来创建一个归档包,即将多个文件一并打包成一个单独的文件。**它的名字来源于过去,意思是磁带归档。档案存储在磁带上的时候。**下面的命令将会创建一个内容是file1
和file2
的文件archive.tar
。
tar -cf archive.tar file1 file2
请注意这里的选项c
代表的是create
,选项f
是用来写文件到归档包中的。如果想要将归档包中的文件提取到当前文件夹中,我们可以使用命令
tar -xf archive.tar
其中选项x
代表的是extract
提取的意思,并且如果想要将文件提取到一个特定的文件夹中,我们可以使用命令
tar -xf archive.tar -C directoryPath
除了这些,我们还可以仅仅使用tar
命令来列举出归档文档中单独的文件
tar -tf archive.tar
// file1
// file2
这里我们需要说明一下,tar
命令也常常会被用来创建一个压缩好的归档文件,就是说tar
命令只管打包不管压缩,而gzip
主要管压缩。那么要想使用tar
命令创建一个压缩好的归档文件,就得需要用到选项z
了:
tar -czf archive.tar.gz file1 file2
上面的命令就像是先创建了一个.tar
归档文件,然后再用gzip
命令压缩该文件成.gz
格式的压缩文件。
如果想要解压缩一个已经打包好的归并文档,我们之前可以使用gunzip
或者gzip -d
来解压缩。但是tar -xf
将会自动识别到它是一个以gzip
形式压缩的文档,并且会自动地帮我们解压缩。
tar -xf archive.tar.gz
alias
经常运行一些程序,而这些程序带有一系列你喜欢的选项,这种现象是非常正常的。例如,拿ls
命令举例,如果使用默认ls
命令的话,会打印出来非常少的信息。但是当你使用-al
选项的时候,它会打印出更多有用的信息,包括修改时间、文件大小、权限所有者、操作权限等,而且还会列举出一些隐藏文件(就是以.
开头的文件)。
那么现在你可以使用alias
命令来创建一个新的命令ll
,同样代表的是ls -al
命令加选项。就像下面的命令:
alias ll="ls -al"
一旦你运行了上述的代码,你就可以使用ll
命令了。
需要知道的是,alias
命令将会一直起作用到终端会话关闭。为了让其永久保持,你需要将它加入到shell
配置中,根据不同的使用可能可能是~/.bashrc
或~/.profile
或~/.bash_profile
文件中。
如果你在命令中使用了变量的话,需要注意引号的使用:
- 双引号:定义该
alias
时的变量值即为调用时的值 - 单引号:更改文件夹后正常使用的值就是单引号后的变量值
alias lsthis="ls $PWD"
alias lscurrent='ls $PWD'
$PWD
代表的是shell
当前所在的文件夹目录,如果你现在导航进入了一个新的文件夹,lscurrent
会列举出新文件夹中的文件,lsthis
则仍然会列举出你定义这个alias
选项时候的文件夹中的文件。
cat
与tail
有一定程度的相似,我们有cat
这个命令,除了上述的使用,cat
这个命令还可以用来在一个文件中添加内容,并且这个会使得该命令的用法更加有力。
对于该命令最简单的用法就是在命令后面加上文件的名字,然后该命令就会在标准输出流中打印出该文件的内容:
cat file
也可以打印多个文件的内容,比如下面的语法:
cat file1 file2
并且重头戏还在下面,就比如使用重定向符>
可以将将多个文件的内容合并到一个新的文件中。
cat file1 file2 > newFile
于是上面的命令将会把上面file1
和file2
的内容重定向到新文件newFile
中,并且该命令将会重写新文件的内容,就是说会覆盖文件原有的内容。但是使用追加符>>
就会将内容追加在新文件newFile
中,而不会更改新文件原有的内容,当然新文件本身不存在的时候将会创建该文件并写入。
cat file1 file2 >> newFile
当查看的是源代码文件的时候,能够看到代码的行数将会是一件非常好的事情,而且这里你就可以使用-n
选项来将他们打印出来。
cat -n file
需要注意到的是cat
命令常被用来和管道运算符|
来结合使用,它可以将cat
命令的输出结果传送到其他的命令中作为该命令的输入来使用。
cat index.js | grep "const"
grep
grep
命令是一个非常实用的工具,当我们熟练掌握它的使用方法之后将会在今后日常的生活中为我们提供极大的帮助。
如果好奇 grep 代表什么意思,这里就再说明一下它是 Global Regular Expression Print的缩写。表示全局正则表达打印
我们可以使用grep
在文件中搜索,或者结合管道标识符|
在其它命令的输出结果中进行搜索。下面就是一个关于我们如何在index.md
文件中找到能够匹配所有带有document.getElementById
行的例子:
grep document.getElementById index.md
我们可以使用选项-n
来展示筛选出来的行号。
grep -n document.getElementById index.md
一个非常有用的事情就是去告知grep
命令打印出匹配行的前两行或后两行,以此来给我们更多的文本信息。为了达到该目的,我们可以使用-C
选项,该选项需要接收一个行数作为参数。
grep -nC 2 document.getElementById index.md
对于grep
命令中的搜索字符串,还可以使用正则表达式,这使得grep
命令的使用能力变得更加强大。
另外使用选项-v
可以反转输出结果,即输出除了匹配行之外的内容:
ls -al | grep -v index.md
tail
对于tail
命令最好的一个用例就是当它和-f
选项同时使用的时候,该命令将会在尾部打开文件,并且监视着文件的变化,每次文件有了新的内容,都将会打印在窗口上,这个方法很适合用来监听log
日志文件,例如
tail -f /var/log/system.log
按下ctrl + C
退出文件监听,我们也可以使用下面的命令打印文件的最后10行:
tail -n 10 <filename>
我们仍然可以使用下面的命令打印文件开头的固定行数,就是在行数前面使用+
运算符:
tail -n +10 <filename>
更多关于tail
的用法我们可以使用man tail
参考手册学习。
diff
diff
是一个非常方便的命令,现在假想你有两个文件,这两个文件几乎包含了相同的信息,但是你不晓得两个文件的区别是什么。那么这个时候diff
命令就会处理这两个文件然后告诉你差异是什么。
diff dogs.txt moredogs.txt
如果使用上面的命令,就会打印出两个文件的差异行,但只是简略的表达一下它们之间的差异,若是交换两个文件的顺序,打印出的也略有不同。
diff -u dogs.txt moredogs.txt
对于-u
选项的使用,我们应该会较为熟悉,因为这个用法和Git
版本控制中展示不同版本之间差异的形式是一样的。
比较文件夹之间的差异是按照一种形式工作的,但是区别在于我们必须使用-r
选项来比较两个文件目录。
需要注意的是,如果我们在意的是文件夹目录中哪两个文件产生了差异,而不是差异的内容是什么,我们可以使用-r
和-q
两个选项。
echo
echo
命令只做一件简单的事情:它会将传它的参数打印出来,比如下面的例子:
echo "Hello World"
将会在终端中打印出来Hello World
文字,并且我们可以把它的输出添加到一个文件的尾部:
echo "Hello World" >> output.txt
同样地,我们也可以直接解析环境变量并传入到echo
命令的输出中,需要注意的是特殊字符需要使用反义字符\
来表达,比如:
echo "The cost is \$5"
echo "The path variable is $PATH"
那么上述代码,第一行就会在终端中输出The cost is $5
,而第二行就会输出一段文字并且输出当前命令所在的环境变量。
上面的使用仅仅是开始,需要知道的是当它和shell
特性结合的时候我们可以做一些非常棒的事情!
- 我们可以
echo
当前文件夹中的文件
echo *
- 我们可以
echo
当前文件夹下以o
开头的所有文件
echo o*
- 任何有效的
bash
命令和特性都可以被使用在此
// 打印出home文件夹路径
echo ~
- 也可以执行命令,并且在终端中(或文件中,取决我们自己的选择)打印出命令执行的结果,需要用双引号包裹起来
echo "$(ls -al)"
- 我们也可以生成一系列字符串,例如
echo {1..5}
// 1 2 3 4 5
basename
假设我们现在有一个文件的路径,例如/Users/falvio/test.txt
,在运行
basename /Users/falvio/test.txt
之后,将会返回一个字符串test.txt
,而如果当我们使用了basename
并且指向了一个目录的话,我们将会得到这个路径的最后一部分。比如我们指向
basename /Users/flavio
那么将会得到flavio
,也就是说basename
会得到给定路径的最后一项文件名字或路径名字。
dirname
而dirname
则不同,它会将给定指向的路径部分返回,比如我们指向
dirname /Users/flavio/test.txt
那么将会返回/Users/flavio
字符串。
chown
在类似于像Linux
或者macOS
这样的操作系统中,每一个文件或者文件目录都有一个所有者owner
。文件的所有者可以对文件做任何事情,并且可以决定该文件的命运。文件所有者(以及root
用户)也可以更改文件所有者为其他的用户,这一操作是通过chown
命令实现的。
chown <owner> <file>
就像这样使用:
chown Mr.L test.txt
例如我们现在有一个被root
用户管理的文件,那么作为其他用户是没有权限向该文件中写入内容的。
那么此时就可以使用chown
命令来将该文件的所属权限改为自己的用户:
sudo chown <current_user> <file_name>
更改一个文件夹目录的所有者权限是非常常见的,并且递归内部的所有文件,包括内部所有子目录以及文件,此时我们可以使用-R
标识:
chown -R <owner> <file>
文件或者文件目录不一定仅仅只有一个所有者。它们也可以有一个用户组,通过此命令,您可以在更改所有者的同时更改它:
chown <owner>:<group> <file>
例如:
chown gitpod:users index.js
除了上面使用chown
更改组的方法,还可以使用chgrp
命令来更改组:
chgrp <group> <file>
chmod
在Linux
和macOS
系统中的所有文件都有三个权限:读、写、执行。当我们使用ls -al
命令打印文件信息的时候,会在第一列出现一串奇怪的字符串,就像drwxr-xr-x
一样,这正式定义了文件或文件目录权限的字符串,现在让我们来剖析一下。
首先,第一个字母代表了文件的类型:
-
代表普通文件d
代表目录l
代表链接
在文件类型之后我们紧跟着有三组数据值:
- 第一组代表了该文件所有者的权限
- 第二组代表了该文件相关联的组成员对该文件的权限
- 第三组代表了其他所有人对该文件的权限
每一组数据都是由三个值组成的,rwx
代表特定的人员具有读、写、执行
的权限,任何一个权限如果没有的话就用-
代替,这就会使得我们形成各种各样的组合类型来代表不同的相关权限,比如rw-
、r--
、r-x
等等。
于是我们可以使用chmod
命令来改变文件的权限。
chmod
命令可以两种方式来使用:
- 特定的符号参数
- 特定的数字参数
使用chmod
命令的时候需要跟上一个空格和一个字母,它们分别代表
a
代表所有用户all
u
代表用户user
g
代表组group
o
代表其他人others
然后我们使用+
或者-
来增加或者删除权限,然后我们就可以输入权限符号了(r
、w
、x
),最后就可以跟上文件或者文件夹目录的名字,下面是几个例子:
chmod a+r filename
# everyone can now read
chmod a+rw filename
# everyone can now read and write
chmod o-rwx filename
# others (not the owner, not in groups can't read, write and execute)
除了这些,我们也可以在+/-
符号之前使用多个用户标识字母
chmod og-r filename
# other and group can't read any filename
如果我们编辑或者设置一个文件夹目录的时候,我们可以使用-r
标识来递归设置文件夹目录中的所有文件。
好的,现在我们可以进入到数字标识的解释中了,如果要使用数字标识,我们需要知道一点二进制的知识,因为最大的数字是7
最小的数字是0
,而其中每个数字都是一个三位的二进制数值转换为十进制之后的内容,其排序是r、w、x
。
read | write | execute | 二进制 | 十进制 | 权限 |
---|---|---|---|---|---|
0 | 0 | 0 | 000 | 0 | — |
0 | 0 | 1 | 001 | 1 | –x |
0 | 1 | 0 | 010 | 2 | -w- |
0 | 1 | 1 | 011 | 3 | -wx |
1 | 0 | 0 | 100 | 4 | r– |
1 | 0 | 1 | 101 | 5 | r-x |
1 | 1 | 0 | 110 | 6 | rw- |
1 | 1 | 1 | 111 | 7 | rwx |
现在我们可以使用三组数字标识来设置文件不同的权限了:
chmod 777 filename
chmod 755 filename
chmod 644 filename
umask
当我们创建了一个文件,我们不需要去明确地表达清楚文件的权限,因为文件的权限是有默认值的。这些默认值也是可以通过使用umask
命令来进行控制和修改的。当我们使用umask
而不传入任何参数的时候,控制台终端将会展示出当前的umask
,比如有一种情况下会输出0022
,那么0022
是表示什么意思呢?它其实是一个十进制的数字来表示权限。另一个较为常见的值是0022
。使用umask -S
命令来看一下不同人群的文件可读性注解:
umask -S
# u=rwx,g=rx,o=rx
在上面的情况下,该文件的所有者有读写执行的权限,同在一个组内的其他用户以及所有其他的用户只具有读和执行的权限。上面所展示的注解中,我们主要更改的也是后面三个数字,具体的数字对应的权限关系如下表:
read | write | execute | 二进制取反 | 十进制 | 权限 |
---|---|---|---|---|---|
0 | 0 | 0 | 111 | 0 | rwx |
0 | 0 | 1 | 110 | 1 | rw- |
0 | 1 | 0 | 101 | 2 | r-x |
0 | 1 | 1 | 100 | 3 | r– |
1 | 0 | 0 | 011 | 4 | -wx |
1 | 0 | 1 | 010 | 5 | -w- |
1 | 1 | 0 | 001 | 6 | –x |
1 | 1 | 1 | 000 | 7 | — |
值得注意的是,这里的数字注释和我们在chmod
,命令中使用的不一样,并且我们详细观察可以发现,这里的二进制取反之后就和之前的二进制含义相同了。所以我们现在可以使用数字注解的格式来设置mask
的值了:
umask 00
du
该命令将会以一个整体的方式来计算文件目录的大小,使用du *
将会独立地计算每个文件的大小:
du *
现在我们来看几个选项:
-m
:以M
的形式展示文件或文件夹的大小-g
:使用G
的形式来展示文件大小-h
:以一种肉眼可见的形式来展示大小,单位会根据真实大小选择-a
:打印文件目录中每个文件的大小
一个非常方便的打印文件目录中较大的几个数据并排好序的命令:
du -h <directory> | sort -nr | head
ps
我们的电脑每时每刻都会运行着许许多多不同的进程,我们可以使用ps
命令来查看所有的进程:
ps
这是运行在当前会话中由用户触发的进程列表,这里我有一些 Fish shell 实例,大部分是通过编辑器内的 VS Code 打开的,还有一个运行网站开发预览的 Hugo 实例。这些只是分配给当前用户的命令。 要列出所有进程,我们需要将一些选项传递给 ps 。最常用的是ps -ax
a
选项还用于列出其他用户进程,而不仅仅是我们自己的进程。x
显示未链接到任何终端的进程(不是由用户通过终端启动的)。
从上面可以看到,更长的命令被截断了,所以我们可以使用ps axww
命令在新的行显示剩下的内容而不是直接截断他们。
我们需要指定 w
两次才能应用此设置,这不是拼写错误。
我们也可以结合grep
以及管道符号来筛选我们所需要的进程,就像这样:
ps -ax | grep node
需要注意的是,通过ps
命令输出内容的列中代表了一些关键的信息:
-
PID
: 第一个信息就是PID
,代表了进程的id
值,当你想要在其他的命令中参考该进程的时候,这个信息是一个关键,比如中断它的时候 -
TT
: 展示给我们进程所使用的终端id
信息 -
STAT
: 告诉我们进程的状态,有如下几种状态I
: 代表进程处于闲置状态(睡眠了20秒以上idle)R
: 代表可运行的进程runnableS
: 代表进程睡眠少于20秒sleepingT
: 代表进程停止stoppedU
: 代表进程处于不可中断等待的过程中Z
: 死进程zombie
-
TIME
: 该进程已经运行了多长时间
top
top
命令用于列出实时运行的进程。top
命令用于显示系统中正在运行的进程的动态实时信息。了解正在发生的事情真的很方便。它的用法很简单,你只需输入top
,终端就会完全沉浸在这个新视图中:
该过程是长期运行的,所以要退出,我们可以输入q
或ctrl-C
。在这里面我们可以获得很多的信息:进程数、正在运行或休眠的进程数、系统负载、CPU 使用率等等。
下面,占用最多内存和CPU
的进程列表不断更新。 默认情况下,正如您从突出显示的%CPU
列中看到的那样,它们按使用的CPU
排序。 您可以添加一个标志来按内存使用情况对进程进行排序:
top -o "%MEM"
kill
Linux
进程可以接收信号并且对其做出反应,这是一种我们和运行中的程序交互的一种方式,kill
命令可以向一个程序发送多种多样的信号。也就是说,kill
命令不仅仅用于结束一个程序进程,就像名字的含义说明的一样,但是这确实是它最主要的工作。我们可以按照下面的方式使用kill
:
kill <PID>
默认情况下,这个命令会发送TERM
信号到PID
所指定的程序中,那么我们就可以使用不同的标识来向程序发送不同的信号:
kill -HUP <PID>
kill -INT <PID>
kill -KILL <PID>
kill -TERM <PID>
kill -CONT <PID>
kill -STOP <PID>
HUP -> hang up
: 当一个开始了某个进程的终端窗口关闭的时候,它会自动地在终止进程之前发送给进程(悬挂了进程之后又有什么效果呢?)INT -> interupt
: 它和当我们按下Ctrl-C
时候发送的信号是一样的,通常情况下会终止该进程KILL
: 它不会发送给进程,而是会发送给操作系统内核(Operating System Kernal),它会立即停止并结束进程TERM -> terminate
: 进程会接收到该信号,之后它会自己停止运行,者也是在我们使用kill
命令之后默认发送的信号CONT -> continue
: 它可以用来重启一个停止的进程STOP
: 它不会发送给进程,而是发送给操作系统内核,随后会立即停止(但不会结束)进程
killall
和kill
命令相似,killall
命令并不是向一个特定id
的进程发送信号,而是一次向多个进程发送信号,语法如下
killall <psName>
参数接收的顾名思义就是程序的名字,这里指的是进程的名字,同样的我们也可以更改不同的信号,纠部过多介绍。
nohup
有时候我们必须在远程机器上运行一个长期存在的进程,并且此时我们需要断开连接,或者我们仅仅是想要在任何客户端与服务器之间的网络问题出现的时候防止命令被关停。
让命令在我们登出或关闭与服务器连接的会话之后仍继续运行的一个方式就是使用nohup
命令,使用nohup <command>
命令让进程即使是在我们退出的时候仍可以继续工作。
which
假设我们有一个可以执行的命令,因为它是在shell
路径中,但是我们想要知道它位于哪个位置,我们可以使用which
命令来获取得到该信息。which
命令将会返回指定的命令所在路径:
which ls
# /bin/ls
which docker
# /usr/local/bin/docker
需要注意的是,which
命令仅仅对于存储在磁盘上的可执行命令有效,对于缩写或者shell
内置函数是无效的。
env
env
命令可以在外部环境中不设置它们的情况下用来传递环境变量。假设现在我们想要运行一个Node.js
app
,并且需要对其设置USER
变量,那么我们可以运行:
env USER=Mr.L node app.js
随后环境变量USER
将会在Node.js
程序中通过process.env
交互进行获取。我们也可以运行使用-i
选项来清空所有的环境变量:
env -i node app.js
这种情况下,我们将会得到一个错误env: node: No such file or directory
因为现在node
是无法获取得到的,因为变量PATH
是没有设置的,所以现在需要传入node
程序的绝对路径:
env -i /usr/local/bin/node app.js
我们也可以使一个变量在运行的程序中不可获取,要实现该功能我们可以使用-u
选项,例如当我们想在程序中移除HOME
变量,我们可以使用下面的命令:
env -u HOME node app.js
ping
该ping
命令将会在本地网络或者互联网络上向一个特定的主机服务器发送请求,我们使用ping <host>
的语法来实现,其中<host>
是服务器的域名或者IP
地址,下面是一个链接google.com
网站的例子:
该命令会向服务器发送请求,然后服务器返回响应数据。ping
命令默认情况下会每隔一秒钟持续不断地向服务器发送请求,直至我们使用ctrl + C
来结束该命令。或者我们也可以在命令使用初期就进行相关的设置,这里就需要用到向ping
命令中传入我们想要尝试发送请求的次数times
,这时我们可以使用-c
选项:ping -c 2 google.com
。
一旦ping
命令停止了之后,将在控制台中打印一些结果数据,其中包括:丢包百分比,以及和网络表现力的相关数据。
在上图中我们可以看到,屏幕上打印了主机的IP
地址,以及得到服务器响应所花费的时间。而且我们需要注意的是,以防请求超时,并不是所有的服务器都支持ping
的。有时侯为了"隐藏"服务器,或者仅仅是为了减少加载,这些事情有可能是故意的。而且ping
数据包也可以被防火墙筛选出来。
ping
是工作在ICMP
协议上的(Internet Control Message Protocol
),它是一个像TCP
或UDP
一样的网络层的一个协议。
请求使用ECHO_REQUEST
消息向服务器发送数据包,并且服务器会返回一个ECHO_REPLY
消息,这里不会深入解释,仅仅提一下这个最基本的概念。
使用ping
是一个知道服务器主机是否可以获取到、请求需要多长时间才能返回来的非常好用的命令(当让这里假设主机是可以支持ping
访问的)。通常情况下,服务器主机在地理位置上离我们越近,请求获得的响应数据返回所需的时间就越少,因为一个简单的物理定律就是远距离的电缆会造成更多的延迟。
下面附一张tldr
关于ping
命令的简单用法介绍:
wget
下面是tldt
中关于wget
命令的简易使用教程:
从上图中我们可以看出,wget
命令主要用来在web
网络上下载文件到本地,它支持HTTP
、HTTPS
、FTP
协议,下面我们来看一下关于wget
命令相关参数选项的使用方法:
- 将一个
URL
中的内容下载到本地文件中,下面的例子中是写到foo
文件中(默认是与网址末位名字相同)
wget https://example.com/foo
- 将一个
URL
中的内容下载到本地文件中,而文件名字可以靠我们自己指定,下面的例子中是写到bar
文件中
wget --output-document bar https://example.com/foo
- 每隔三秒发送请求下载一个单网页以及它所有的资源(包括脚本、样式表、图片等等)
wget --page-requisites --convert-links --wait=3 https://example.com/somepage.html
- 将网站上所有列举出来的文件下载到一个目录中以及子目录中
wget --mirror --no-parent https://example.com/somepath/
curl
关于curl
命令的介绍可以参考下图中tldr
库中给出的简易使用说明:
从上图中可以看出来,curl
命令主要是用来从服务器或向服务器中传送数据的,它支持大部分的网络协议,其中包括了HTTP
、FTP
、POP3
,关于该命令更多的信息可以参考https://curl.se/docs/manpage.html。接下来我们就来看一下该命令相关的参数选项。
- 当我们想要将
curl
命令获取到的数据写入到某个文件中的时候,可以使用--output
选项,使用语法如下所示,其中,<url>
指的是服务器地址或主机域名,<file>
指的是结果要写入的文件路径(可以是相对路径也可以是绝对路径)
curl <url> --output <file>
- 如果我们想要在网站上下载某些资源的时候,
curl
提供了--remote-name
选项,可以帮助我们将网站上的文件下载下来并按照URL
中指示的名字那样将文件保存下来。
curl --remote-name <URL>
- 如果想要发送带有额外
header
的请求,我们可以使用--header
选项,并且可以使用--request
选项更改请求的方式,如下所示
curl --header 'X-My-Header: 123' --request PUT <URL>
- 同样的,我们也可以使用
--data
选项发送一个带有JSON
格式数据的请求
curl --data '{"name": "bob"}' --header 'Content-Type: application/json' <URL>
关于curl
命令的使用还有许多其他的内容,这里就先简单介绍以上几种方式,需要谨记的是curl
命令的主要作用,就是实现我们的终端和一些远程服务器通信,其中就涉及到了一系列的参数选项来保证请求的完整性。
scp
scp
命令的全程可以理解为secure copy
,就是通过ssh
并使用Secure Copy
传输协议在两个主机之间安全复制文件。接下来我们可以看一些关于scp
命令相关用法:
- 将本地文件传输到一个远程主机:
scp <local_file_path> remote_host:<remote_file_path>
- 当连接到远程主机的时候使用一个特定的端口:
scp -P <port_number> <local_file_path> remote_host:<remote_file_path>
- 从远端主机中复制文件到本地目录中:
scp remote_host:<remote_file_path> <local_directory_path>
- 递归式地在远程主机中复制一个文件夹目录中的所有内容到本地目录中:
scp -r remote_host:<remote_directory_path> <local_directory_path>
- 使用特定的用户名连接远程主机:
scp <local_file_path> <remote_username>@remote_host:<remote_directory_path>
su
当我们使用一个用户登录了终端之后,我们可能需要去更改另一个用户。例如,我们现在以管理员root
身份登录来执行一些维护操作,但是现在我们想要将更改为另一位用户,这时我们可以使用su
命令来达到此目的:
su <username>
例如su leo
当我们作为一位用户登录之后,如果不带任何参数的使用su
命令的时候,shell
终端将会默认我们想要登录root
管理员用户,于是会提示我们输入管理员用户的密码。在另一位用户切换成功之后,su
命令将会开启一个新的shell
终端来方便该用户的某些操作,当然,我们作为该用户结束相关操作之后,使用exit
命令将会关闭该shell
终端并且返回到当前用户的shell
终端界面。
sudo
sudo
命令通常被用来作为root
管理员身份运行一个其他命令。在使用sudo
命令之前,我们需要通过输入我们本人用户的密码来使用它,注意是我们自己的用户密码,而非管理员用户的密码。接下来我们就可以使用sudo
命令来作为root
管理员用户运行其他的命令了。
我们可以使用sudo -i
命令以root
管理员身份开启一个新的shell
终端。
在一个多用户服务器环境的shell
终端中,命令使用的权限是被高度设置好的,意味着一部分用户将会获得使用sudo
命令运行某些特定命令的权限。例如,我们可以使用下面的命令编辑系统的配置文件:
sudo nano /etc/hosts
否则如果我们没有权限的话,在文件保存的时候将会失败。
需要注意的是,我们可以使用-u
选项来选择任何一个用户运行某个命令,只是在不使用-u
选项的时候,root
管理员用户是默认的,就像下面一样:
sudo -u Leo ls /Users/Leo