Linux命令行

一、基本的bash shell命令

1.浏览文件系统

遍历目录

在Linux文件系统上,可以使用切换目录命令cd将shell会话切换到另一个目录。cd命令的格式非常简单:

cd destination

destination参数可以用两种方式表示:一种是使用绝对文件路径,另一种是使用相对文件路径。

绝对文件路径:

zhangwenming@ubuntu61-PowerEdge-R730:/$ cd /home/zhangwenming/

相对文件路径:

zhangwenming@ubuntu61-PowerEdge-R730:/home$ cd zhangwenming/

pwd命令可以显示出shell会话的当前目录,这个目录被称为当前工作目录:

zhangwenming@ubuntu61-PowerEdge-R730:~$ pwd
/home/zhangwenming

可以使用绝对文件路径切换到Linux虚拟目录结构中的任何一级。还可以从Linux虚拟目录中的任何一级跳回主目录:

zhangwenming@ubuntu61-PowerEdge-R730:~$ pwd
/home/zhangwenming
zhangwenming@ubuntu61-PowerEdge-R730:~$ cd /home/share/
zhangwenming@ubuntu61-PowerEdge-R730:/home/share$ cd
zhangwenming@ubuntu61-PowerEdge-R730:~$ pwd
/home/zhangwenming

有两个特殊字符可用于相对文件路径中:

  • 单点符(.),表示当前目录;
  • 双点符(..),表示当前目录的父目录。

2.文件和目录列表

基本列表功能

ls命令最基本的形式会显示当前目录下的文件和目录:

zhangwenming@ubuntu61-PowerEdge-R730:~$ ls
examples.desktop  veridex  workspace

要把隐藏文件和普通文件及目录一起显示出来,就得用到-a参数:

zhangwenming@ubuntu61-PowerEdge-R730:~$ ls -a
.   .bash_history  .bashrc  .config  examples.desktop  .p4merge  .p4tickets  veridex    .Xauthority
..  .bash_logout   .cache   .dbus    .local            .p4qt     .profile    workspace

-R参数是ls命令可用的另一个参数,叫作递归选项。它列出了当前目录下包含的子目录中的文件:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ pwd
/home/zhangwenming/workspace/Tomorrow
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -R
.:
ZWM

./ZWM:
test.txt

显示长列表

在基本的输出列表中,ls命令并未输出太多每个文件的相关信息。要显示附加信息,另一个常用的参数是-l。-l参数会产生长列表格式的输出,包含了目录中每个文件的更多相关信息:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 4
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:37 android.txt
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 17:29 ZWM

每一行都包含了关于文件(或目录)的下述信息:

  • 文件类型,比如目录(d)、文件(-)、字符型文件(c)或块设备(b);
  • 文件的权限;
  • 文件的硬链接总数;
  • 文件属主的用户名;
  • 文件属组的组名;
  • 文件的大小(以字节为单位);
  • 文件的上次修改时间;
  • 文件名或目录名。

过滤输出列表

默认情况下,ls命令会输出目录下的所有非隐藏文件。有时这个输出会显得过多,幸而ls命令还支持在命令行中定义过滤器,它会用过滤器来决定应该在输出中显示哪些文件或目录。

简单文本匹配:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 4
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:37 android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:48 java.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:48 kotlin.txt
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 17:29 ZWM
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:37 android.txt

当用户指定特定文件的名称作为过滤器时,ls命令只会显示该文件的信息。有时可能不知道要找的那个文件的确切名称。ls命令能够识别标准通配符,并在过滤中用它们进行模式匹配:

  • 问号(?)代表一个字符;
  • 星号(*)代表零个或多个字符。

例如:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 4
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:37 android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:48 anko.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:48 java.txt
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 17:29 ZWM
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l an?o.txt
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:48 anko.txt
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l an*
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:37 android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:48 anko.txt

除了星号和问号之外,还有更多的元字符通配符可用于文件扩展匹配。可以使用中括号:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l an[kd]*
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:37 android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:48 anko.txt

也可以指定字符范围,例如字母范围[a - i]:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l an[a-k]*
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:37 android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:48 anko.txt

另外,可以使用感叹号(!)将不需要的内容排除在外:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l an[!k]*
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:37 android.txt

3.处理文件

创建文件

可用touch命令轻松创建空文件:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ touch test_one
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 4
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:37 android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:48 anko.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 18:41 test_one
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 17:29 ZWM

touch命令还可用来改变文件的修改时间,这个操作并不需要改变文件的内容:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ touch test_one
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 4
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:37 android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:48 anko.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 18:43 test_one
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 17:29 ZWM

复制文件

通过cp命令可以将文件系统中的文件和目录从一个位置复制到另一个位置。cp命令的语法:

cp source destination

当source和destination参数都是文件名时,cp命令将源文件复制成一个新文件,并且以destination命名。新文件就像全新的文件一样,有新的修改时间:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ cp test_one test_two
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 4
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:37 android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:48 anko.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 18:43 test_one
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 18:52 test_two
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 17:29 ZWM

如果目标文件已经存在,cp命令可能并不会提醒这一点,最好是加上-i选项,强制询问是否需要覆盖已有的文件:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ cp -i test_one test_two
cp: overwrite ‘test_two’? y
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 4
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:37 android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 18:43 test_one
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 18:55 test_two
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 17:29 ZWM

也可将文件复制到现有目录中:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ cp -i test_one ./ZWM/
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l -R
.:
total 4
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:37 android.txt
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 18:43 test_one
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 18:55 test_two
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 18:58 ZWM

./ZWM:
total 0
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 18:58 test_one
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:29 test.txt

cp命令的-R参数威力强大,可以用它在一条命令中递归地复制整个目录的内容:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -d ZW*
ZWM
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l ZWM/
total 0
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 18:58 test_one
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:29 test.txt
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ cp -R ZWM/ MOD_ZWM
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -d *ZWM
MOD_ZWM  ZWM
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l MOD_ZWM/
total 0
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 19:02 test_one
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 19:02 test.txt

也可以在cp命令中使用通配符:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ cp -i test*one test_two
cp: overwrite ‘test_two’? y
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 8
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:37 android.txt
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 19:02 MOD_ZWM
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 18:43 test_one
-rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 19:06 test_two
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 18:58 ZWM

制表键自动补全

制表键自动补全允许你在输入文件名或目录名时按一下制表键,让shell帮忙将内容补充完整。

链接文件

链接文件是Linux文件系统的一个优势。如需要在系统上维护同一文件的两份或多份副本,除了保存多份单独的物理文件副本之前,还可以采用保存一份物理文件副本和多个虚拟副本的方法。这种虚拟的副本就称为链接。链接是目录中指向文件真实位置的占位符。在Linux中有两种不同类型的文件链接:

  • 符号链接
  • 硬链接

符号链接就是一个实实在在的文件,它指向存放在虚拟目录结构中某个地方的另一个文件。这两个通过符号链接在一起的文件,彼此的内容并不相同。要为一个文件创建符号链接,原始文件必须事先存在。然后可以使用ln命令以及-s选项来创建符号链接:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l test_one
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 18:43 test_one
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ln -s test_one s1_test_one
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l *test_one
lrwxrwxrwx 1 zhangwenming zhangwenming 8  9月  1 21:04 s1_test_one -> test_one
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 18:43 test_one

符号链接的文件大小和数据文件的文件大小不同。另一种证明链接文件是独立文件的方法是查看inode编号。文件或目录的inode编号是一个用于标识的唯一数字,这个数字由内核分配给文件系统中的每一个对象。要查看文件或目录的inode编号,可以给ls命令加入-i参数:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -i *test_one
29163608 s1_test_one  29163602 test_one

硬链接会创建独立的虚拟文件,其中包含了原始文件的信息及位置。但是它们从根本上而言是同一个文件。引用硬链接文件等同于引用了源文件。要创建硬链接,原始文件也必须事先存在,只不过这次使用ln命令时不再需要加入额外的参数了:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l test_two
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 19:06 test_two
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ln test_two h1_test_two
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -li *test_two
29163603 -rw-rw-r-- 2 zhangwenming zhangwenming 0  9月  1 19:06 h1_test_two
29163603 -rw-rw-r-- 2 zhangwenming zhangwenming 0  9月  1 19:06 test_two

注意,带有硬链接的文件共享inode编号,这是因为它们终归是同一个文件。还要注意的是,链接计数(列表中第三项)显示这两个文件都有两个链接。另外,它们的文件大小也一模一样。

只能对处于同一存储媒体的文件创建硬链接。要想在不同存储媒体的文件之间创建链接, 只能使用符号链接。

重命名文件

在Linux中,重命名文件称为移动。mv命令可以将文件和目录移动到另一个位置或重新命名:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -li android.txt
29163599 -rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:37 android.txt
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ mv android.txt Android.txt
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -li *droid.txt
29163599 -rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:37 Android.txt

也可以使用mv来移动文件的位置:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -li ZWM/
total 0
29163604 -rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 18:58 test_one
29163598 -rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:29 test.txt
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ mv test_two ZWM/
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -li ZWM/
total 0
29163604 -rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 18:58 test_one
29163603 -rw-rw-r-- 2 zhangwenming zhangwenming 0  9月  1 19:06 test_two
29163598 -rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:29 test.txt

和刚才一样,这个操作并没有改变文件的inode编号或时间戳。

和cp命令类似,也可以在mv命令中使用-i参数。这样在命令试图覆盖已有的文件时,你就会得到提示:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ mv -i test_two ZWM/
mv: overwrite ‘ZWM/test_two’? y
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -li ZWM/
total 0
29163604 -rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 18:58 test_one
29163609 -rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  2 01:46 test_two
29163598 -rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:29 test.txt

也可以使用mv命令移动整个目录及内容:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ mv ZWM/ NEW_ZWM/
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l NEW_ZWM/
total 0
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 18:58 test_one
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  2 01:46 test_two
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  1 17:29 test.txt

删除文件

bash shell中删除文件的命令是rm。rm命令的基本格式非常简单:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ rm -i test_one
rm: remove regular file ‘test_one’? y
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -li
total 8
29163599 -rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 17:37 Android.txt
29163603 -rw-rw-r-- 1 zhangwenming zhangwenming    0  9月  1 19:06 h1_test_two
29163605 drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  1 19:02 MOD_ZWM
29163594 drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  2 01:47 NEW_ZWM
29163608 lrwxrwxrwx 1 zhangwenming zhangwenming    8  9月  1 21:04 s1_test_one -> test_one

如果要删除很多文件且不受提示符的打扰,可以用-f参数强制删除。小心为妙!

4.处理目录

创建目录

在Linux中创建目录很简单,用mkdir命令即可:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ mkdir New_Dir
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -ld New_Dir/
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  2 02:29 New_Dir/

要想同时创建多个目录和子目录,需要加入-p参数:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ mkdir -p New_Dir/Sub_Dir/Under_Dir
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -ld New_Dir/Sub_Dir/Under_Dir/
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  2 02:33 New_Dir/Sub_Dir/Under_Dir/

删除目录

删除目录的基本命令是rmdir:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ rmdir New_Dir/
rmdir: failed to remove ‘New_Dir/’: Directory not empty

默认情况下,rmdir命令只删除空目录,得先把目录中的文件删掉,然后才能在空目录上使用rmdir命令。

也可以在整个非空目录上使用rm命令。使用-r选项使得命令可以向下进入目录,删除其中的文件,然后再删除目录本身:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ rm -ri New_Dir/
rm: descend into directory ‘New_Dir/’? y
rm: remove directory ‘New_Dir/Sub_Dir’? y
rm: remove directory ‘New_Dir/’? y
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -ld New_Dir/
ls: cannot access New_Dir/: No such file or directory

一口气删除目录及其所有内容的终极大发就是使用带有-r参数和-f参数的rm命令:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ mkdir -p NewDir/SubDir/UnderDir
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ rm -rf NewDir/

5.查看文件内容

查看文件类型

file命令能够探测文件的内部,并决定文件是什么类型的:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ file Android.txt
Android.txt: ASCII text

file命令不仅能确定文件中包含的文本信息,还能确定该文本文件的字符编码。

可以使用file命令作为另一种区分目录的方法:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ file NEW_ZWM/
NEW_ZWM/: directory

查看整个文件

cat命令是显示文本文件中所有数据的得力工具:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ cat Android.txt
Hello, Android!

Line 3.

-n参数会给所有的行加上行号:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ cat -n Android.txt
     1  Hello, Android!
     2
     3  Line 3.

如果只想给有文本的行加上行号,可以用-b参数:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ cat -b Android.txt
     1  Hello, Android!

     2  Line 3.

如果不想让制表符出现,可以用-T参数,-T参数会用^I字符组合去替换文中的所有制表符。

cat命令的主要缺陷是:一旦运行,你就无法控制后面的操作。more命令会显示文本文件的内容,但会在显示每页数据之后停下来:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ more Android.txt

less命令是more命令的升级版,它提供了一些极为实用的特性,能够实现在文本文件中前后翻动,而且还有一些高级搜索功能。

查看部分文件

tail命令会显示文件最后几行的内容。默认情况下,它会显示文件的末尾10行:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ tail Android.txt

可以向tail命令中加入-n参数来修改所显示的行数:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ tail -n 3 Android.txt

-f参数是tail命令的一个突出特性。它允许你在其他进程使用该文件时查看文件的内容。tail命令会保持活动状态,并不断显示添加到文件中的内容。这是实时监测系统日志的绝妙方式。

head命令会显示文件开头那些行的内容。默认情况下,它会显示文件前10行的文本:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ head Android.txt

类似于tail命令,head命令也支持-n参数,可以指定想要显示的内容:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ head -3 Android.txt

文件的开头通常不会改变,因此head命令不像tail命令那样支持-f参数特性。head命令是一种查看文件起始部分内容的便捷方法。

二、更多的bash shell命令

1.监测程序

探查进程

当程序运行在系统上时,我们称之为进程。想监测这些进程,需要熟悉ps命令的用法。默认情况下,ps命令只会显示运行在当前控制台下的属于当前用户的进程:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ps
   PID TTY          TIME CMD
 90995 pts/13   00:00:01 bash
 94755 pts/13   00:00:00 ps

Linux系统中使用的GNU ps命令支持3种不同类型的命令行参数:

  • Unix风格的参数,前面加单破折线
  • BSD风格的参数,前面不加破折线
  • GNU风格的长参数,前面加双破折线

Unix风格的参数:

如果你想查看系统上运行的所有进程,可用-ef参数组合(ps命令运行你像这样把参数组合在一起):

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0  2019 ?        00:00:09 /sbin/init
root          2      0  0  2019 ?        00:00:08 [kthreadd]
root          3      2  0  2019 ?        00:03:22 [ksoftirqd/0]
root          5      2  0  2019 ?        00:00:00 [kworker/0:0H]
root          6      2  0  2019 ?        00:00:00 [kworker/u384:0]
root          8      2  0  2019 ?        03:10:44 [rcu_sched]
...

-e参数指定显示所有运行在系统上的进程,-f参数则扩展了输出,这些扩展的列包含了有用的信息:

  • UID:启动这些进程的用户
  • PID:进程的进程ID
  • PPID:父进程的进程号(如果该进程是由另一个进程启动的)
  • C:进程生命周期中的CPU利用率
  • STIME:进程启动时的系统时间
  • TTY:进程启动时的终端设备
  • TIME:运行进程需要的累计CPU时间
  • CMD:启动的程序名称

如果想要获得更多的信息,可采用-l参数,它会产生一个长格式输出:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ps -l
F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1009  90995  90992  0  80   0 -  6796 wait   pts/13   00:00:01 bash
0 R  1009  94776  90995  0  80   0 -  3557 -      pts/13   00:00:00 ps

注意使用了-l参数之后多出的那些列:

  • F:内核分配给进程的系统标记
  • S:进程的状态(O代表正在运行;S代表在休眠;R代表可运行,正等待运行;Z代表僵化,进程已结束但父进程已不存在;T代表停止)
  • PRI:进程的优先级(越大的数字代表越低的优先级)
  • NI:谦让度值用来参与决定优先级
  • ADDR:进程的内存地址
  • SZ:假如进程被换出,所需交换空间的大致大小
  • WCHAN:进程休眠的内核函数的地址

实时监测进程

ps命令虽然在收集运行在系统上的进程信息时非常有用,但也有不足之处:它只能显示某个特定时间点的信息。top命令跟ps命令相似,能够显示进程信息,但它是实时显示的:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ top
top - 04:36:29 up 283 days,  2:47,  1 user,  load average: 1.15, 1.16, 1.07
Tasks: 714 total,   1 running, 713 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.1 us,  0.4 sy,  0.0 ni, 93.7 id,  5.8 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:  32832496 total, 31276892 used,  1555604 free, 11233848 buffers
KiB Swap: 33457148 total,   223360 used, 33233788 free.   942520 cached Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 94748 root      20   0   12028   2864   2104 D   6.0  0.0   2:04.20 du
    12 root      20   0       0      0      0 S   0.7  0.0   5:17.36 rcuos/3
 94794 zhangwe+  20   0   29660   3688   2660 R   0.7  0.0   0:00.08 top
     8 root      20   0       0      0      0 S   0.3  0.0 190:51.99 rcu_sched
  4476 root      20   0       0      0      0 S   0.3  0.0   7:14.67 jbd2/sdb-8
     1 root      20   0   37632   3124   1252 S   0.0  0.0   0:09.26 init
...

结束进程

kill命令可通过进程ID(PID)给进程发信号。默认情况下,kill命令会向命令行中列出的全部PID发送一TERM信号。遗憾的是,你只能用进程的PID而不能用命令名,所以kill命令有时并不好用。要发送进程信号,你必须是进程的属主或登录为root用户:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ kill 3940

TERM信号告诉进程可能的话就停止运行。不过,如果有不服管教的进程,那它通常会忽略这个请求。如果要强制停止,-s参数支持指定其他信号(用信号名或信号值):

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ kill -s HUP 3940

kill命令不会有任何输出,要检查kill命令是否有效,可再运行ps或top命令,看看问题进程是否已停止。

killall命令非常强大,它支持通过进程名而不是PID来结束进程。killall命令也支持通配符,这在系统因负载过大而变得很慢时很有用:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ killall http*

2.监测磁盘空间

挂载存储媒体

Linux文件系统将所有的磁盘都并入一个虚拟目录下。在使用新的存储媒体之前,需要把它放到虚拟目录下,这项工作称为挂载。Linux上用来挂载媒体的命令叫作mount。默认情况下,mount命令会输出当前系统上挂载的设备列表:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ mount
/dev/sda1 on / type ext4 (rw,errors=remount-ro)
proc on /proc type proc (rw,noexec,nosuid,nodev)
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
...

手动挂载媒体设备的基本命令:

mount -t type device directory

从Linux系统上移除一个可移动设备时,不能直接从系统上移除,而应该先卸载。卸载设备的命令是umount。umount命令的格式非常简单:

umount [directory | device]

使用df命令

有时你需要知道在某个设备上还有多少磁盘空间,df命令可以让你很方便地查看所有已挂载磁盘的使用情况:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ df
Filesystem      1K-blocks       Used  Available Use% Mounted on
udev             16405180          4   16405176   1% /dev
tmpfs             3283252      26512    3256740   1% /run
/dev/sda1       254766660   61597956  180204252  26% /
none                    4          0          4   0% /sys/fs/cgroup
none                 5120          0       5120   0% /run/lock
none             16416248       4044   16412204   1% /run/shm
none               102400         48     102352   1% /run/user
/dev/sdb       5811065560 1461694220 4056487680  27% /home

df命令有一些命令行参数可用,但基本上不会用到。一个常用的参数是-h。它会把输出中的磁盘空间按照用户易读的形式显示,通常用M来替代兆字节,用G替代吉字节:

zhangwenming@ubuntu61-PowerEdge-R730:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev             16G  4.0K   16G   1% /dev
tmpfs           3.2G   26M  3.2G   1% /run
/dev/sda1       243G   59G  172G  26% /
none            4.0K     0  4.0K   0% /sys/fs/cgroup
none            5.0M     0  5.0M   0% /run/lock
none             16G  4.0M   16G   1% /run/shm
none            100M   48K  100M   1% /run/user
/dev/sdb        5.5T  1.4T  3.8T  27% /home

使用du命令

du命令可以显示某个特定目录(默认情况下是当前目录)的磁盘使用情况。这一方法可用来快速判断系统上某个目录下是不是有超大文件。默认情况下,du命令会显示当前目录下所有的文件、目录和子目录的磁盘使用情况,它会以磁盘块为单位来表明每个文件或目录占用了多大存储空间:

zhangwenming@ubuntu61-PowerEdge-R730:~$ du
4       ./.config/enchant
12      ./.config/gedit
4       ./.config/ibus/bus
8       ./.config/ibus
8       ./.config/dconf
8       ./.config/Perforce
...

下面是能让du命令用起来更方便的几个命令行参数:

  • -c:显示所有已列出文件总的大小
  • -h:按用户易读的格式输出大小,即用K替代千字节,用M来替代兆字节,用G替代吉字节
  • -s:显示每个输出参数的总计
zhangwenming@ubuntu61-PowerEdge-R730:~$ du -h
4.0K    ./.config/enchant
12K     ./.config/gedit
4.0K    ./.config/ibus/bus
8.0K    ./.config/ibus
8.0K    ./.config/dconf
8.0K    ./.config/Perforce

3.处理数据文件

排序数据

默认情况下,sort命令按照会话指定的默认语言的排序规则对文本文件中的数据行排序:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ sort Android.txt
five
four
one
three
two

-n参数可以对数字按值排序:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ sort -n Android.txt
1
3
5
7
9

搜索数据

grep命令的命令行格式如下:

grep [options] pattern [file]

gerp命令会在输入或指定的文件中查找包含匹配指定模式的字符的行。grep的输出就是包含了匹配模式的行:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ grep a Android.txt
May
Jan

如果要进行反向搜索(输出不匹配该模式的行),可加-v参数:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ grep -v a Android.txt
Apr
Feb
Nov

如果要显示匹配模式的行所在的行号,可加-n参数:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ grep -n a Android.txt
2:May
3:Jan

如果只想知道有多少行含有匹配的模式,可用-c参数:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ grep -c a Android.txt
2

如果要指定多个匹配模式,可用-e参数来指定每个模式:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ grep -e a -e A Android.txt
Apr
May
Jan

默认情况下,grep命令用基本的Unix风格正则表达式来匹配模式。Unix风格正则表达式采用特殊字符来定义怎样查找匹配的模式:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ grep [aA] Android.txt
Apr
May
Jan

压缩数据

gzip是Linux上最流行的压缩工具。gzip软件包是GNU项目的产物,意在编写一个能够替代原先Unix中compress工具的免费版本。这个软件包含有下面的工具:

  • gzip:用来压缩文件
  • gzcat:用来查看压缩过的文本文件的内容
  • gunzip:用来解压文件
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l Android.txt.gz
-rw-rw-r-- 1 zhangwenming zhangwenming 52  9月  2 17:38 Android.txt.gz

gzip命令会压缩你在命令行指定的文件。也可以在命令行指定多个文件名甚至用通配符来一次性批量压缩文件:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ gzip *roid*
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l *roid*
-rw-rw-r-- 1 zhangwenming zhangwenming 52  9月  2 17:38 Android.txt.gz
-rw-rw-r-- 1 zhangwenming zhangwenming 42  9月  2 18:25 Droid.txt.gz

归档数据

虽然zip命令能够很好地将数据压缩和归档进单个文件,但它不是Unix和Linux中的标准归档工具。目前,Unix和Linux上最广泛使用的归档工具是tar命令。tar命令的格式:

tar function [options] object1 object2 ...

可以用下列命令来创建一个归档文件:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ tar -cvf test.tar NEW_ZWM/ MOD_ZWM/
NEW_ZWM/
NEW_ZWM/test_two
NEW_ZWM/test.txt
NEW_ZWM/test_one
MOD_ZWM/
MOD_ZWM/test.txt
MOD_ZWM/test_one

接着用下列命令列出tar文件的内容(但并不提取文件):

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ tar -tf test.tar
NEW_ZWM/
NEW_ZWM/test_two
NEW_ZWM/test.txt
NEW_ZWM/test_one
MOD_ZWM/
MOD_ZWM/test.txt
MOD_ZWM/test_one

最后用下列命令从tar文件中提取内容:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ tar -xvf test.tar
NEW_ZWM/
NEW_ZWM/test_two
NEW_ZWM/test.txt
NEW_ZWM/test_one
MOD_ZWM/
MOD_ZWM/test.txt
MOD_ZWM/test_one

如果tar文件是从一个目录结构创建的,那整个目录结构都会在当前目录下重新创建。

三、理解shell

1.shell的类型

查看默认shell程序:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ cat /etc/passwd
zhangwenming:x:1009:1009:,,,:/home/zhangwenming:/bin/bash
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -lF /bin/bash
-rwxr-xr-x 1 root root 1021112  5月 16  2017 /bin/bash*

由于bash shell的广为流行,很少有人使用其他的shell作为默认shell。

2.shell的父子关系

用于登录某个虚拟控制器终端或在GUI中运行终端仿真器时所启动的默认的交互shell,是一个父shell。在CLI提示符后输入/bin/bash命令或其他等效的bash命令时,会创建一个新的shell程序,这个shell程序被称为子shell,子shell也拥有CLI提示符,同样会等待命令输入:

zhangwenming@ubuntu61-PowerEdge-R730:~$ ps -f
UID         PID   PPID  C STIME TTY          TIME CMD
zhangwe+  97900  97899  1 19:18 pts/13   00:00:00 -bash
zhangwe+  97976  97900  0 19:19 pts/13   00:00:00 ps -f
zhangwenming@ubuntu61-PowerEdge-R730:~$ bash
zhangwenming@ubuntu61-PowerEdge-R730:~$ ps -f
UID         PID   PPID  C STIME TTY          TIME CMD
zhangwe+  97900  97899  0 19:18 pts/13   00:00:00 -bash
zhangwe+  97977  97900  1 19:19 pts/13   00:00:00 bash
zhangwe+  97989  97977  0 19:19 pts/13   00:00:00 ps -f

进程就是正在运行的程序。bash shell是一个程序,当它运行的时候,就成为了一个进程。一个运行着的shell就是某种进程而已。因此,在说到运行一个bash shell的时候,经常会看到shell和进程这两个词交换使用。

可以利用exit命令有条不紊地退出子shell。

别出心裁的子shell用法

sleep命令接受一个参数,该参数是你希望进程等待(睡眠)的秒数:

zhangwenming@ubuntu61-PowerEdge-R730:~$ sleep 5

要想将命令置入后台,可以在命令行末尾加上字符&:

zhangwenming@ubuntu61-PowerEdge-R730:~$ sleep 5&
[1] 98204
zhangwenming@ubuntu61-PowerEdge-R730:~$ ps -f
UID         PID   PPID  C STIME TTY          TIME CMD
zhangwe+  97900  97899  0 19:18 pts/13   00:00:00 -bash
zhangwe+  98204  97900  0 21:14 pts/13   00:00:00 sleep 5
zhangwe+  98205  97900  0 21:14 pts/13   00:00:00 ps -f
zhangwenming@ubuntu61-PowerEdge-R730:~$ ps -f
UID         PID   PPID  C STIME TTY          TIME CMD
zhangwe+  97900  97899  0 19:18 pts/13   00:00:00 -bash
zhangwe+  98207  97900  0 21:14 pts/13   00:00:00 ps -f
[1]+  Done                    sleep 5

除了ps命令,也可以使用jobs命令来显示后台作业信息。jobs命令可以显示出当前运行在后台模式中的所有用户的进程(作业):

zhangwenming@ubuntu61-PowerEdge-R730:~$ sleep 5&
[1] 98241
zhangwenming@ubuntu61-PowerEdge-R730:~$ jobs
[1]+  Running                 sleep 5 &

利用jobs命令的-l(字母L的小写形式)选项,还能够看到更多的相关信息:

zhangwenming@ubuntu61-PowerEdge-R730:~$ jobs -l
[2]+ 98279 Running                 sleep 5 &

协程

协程可以同时做两件事,它在后台生成一个子shell,并在这个子shell中执行命令。要进行协程处理,得使用coproc命令,还有要在子shell中执行的命令:

zhangwenming@ubuntu61-PowerEdge-R730:~$ coproc sleep 10
[1] 98295
zhangwenming@ubuntu61-PowerEdge-R730:~$ jobs
[1]+  Running                 coproc COPROC sleep 10 &

可以使用命令的扩展语法自己设置进程名字:

zhangwenming@ubuntu61-PowerEdge-R730:~$ coproc My_Job { sleep 10; }
[1] 98304
zhangwenming@ubuntu61-PowerEdge-R730:~$ jobs
[1]+  Running                 coproc My_Job { sleep 10; } &

只有在拥有多个协程的时候才需要对协程进行命名,因为你得和它们进行通信。否则的话,让coproc命令将其设置成默认的名字COPROC就行了。

3.理解shell的内建命令

外部命令

外部命令,有时候也被称为文件系统命令,是存在于bash shell之外的程序。它们并不是shell程序的一部分。外部命令程序通常位于/bin、/usr/bin、/sbin或/usr/sbin中。

ps就是一个外部命令:

zhangwenming@ubuntu61-PowerEdge-R730:~$ which ps
/bin/ps
zhangwenming@ubuntu61-PowerEdge-R730:~$ type -a ps
ps is /bin/ps
zhangwenming@ubuntu61-PowerEdge-R730:~$ ls -l /bin/ps
-rwxr-xr-x 1 root root 93232  5月 14  2018 /bin/ps

当外部命令执行时,会创建出一个子进程。这种操作被称为衍生。外部命令ps很方便显示出它的父进程以及自己所对应的衍生子进程:

zhangwenming@ubuntu61-PowerEdge-R730:~$ ps -f
UID         PID   PPID  C STIME TTY          TIME CMD
zhangwe+  97900  97899  0 19:18 pts/13   00:00:00 -bash
zhangwe+  98382  97900  0 21:51 pts/13   00:00:00 ps -f

当进程必须执行衍生操作时,它需要花费时间和精力来设置新子进程的环境,所以说,外部命令多少还是有代价的。

内建命令

内建命令和外部命令的区别在于前者不需要使用子进程来执行。它们已经和shell编译成了一体,作为shell工具的组成部分存在。不需要借助外部程序文件来运行。

cd和exit命令都内建于bash shell,可以利用type命令来了解某个命令是否是内建的:

zhangwenming@ubuntu61-PowerEdge-R730:~$ type cd
cd is a shell builtin
zhangwenming@ubuntu61-PowerEdge-R730:~$ type exit
exit is a shell builtin

因为既不需要通过衍生出子进程来执行,也不需要打开程序文件,内建命令的执行速度要更快,效率也更高。

要注意,有些命令有多种实现,例如echo和pwd既有内建命令也有外部命令,两种实现略有不同。要查看命令的不同实现,使用type命令的-a选项:

zhangwenming@ubuntu61-PowerEdge-R730:~$ type -a echo
echo is a shell builtin
echo is /bin/echo
zhangwenming@ubuntu61-PowerEdge-R730:~$ which echo
/bin/echo

命令type -a显示出了每个命令的两种实现。注意,which命令只显示出了外部命令文件。

使用history命令:

一个有用的内建命令是history命令。bash shell会跟踪你用过的命令。你可以唤回这些命令并重新使用。

要查看最近用过的命令列表,可以输入不带选项的history命令:

zhangwenming@ubuntu61-PowerEdge-R730:~$ history

输入!!,然后按回车键就能够唤出刚刚用过的那条命令来使用:

zhangwenming@ubuntu61-PowerEdge-R730:~$ pwd
/home/zhangwenming
zhangwenming@ubuntu61-PowerEdge-R730:~$ !!
pwd
/home/zhangwenming

你可以唤回历史列表中任意一条命令,只需要输入惊叹号和命令在历史列表中的编号即可:

zhangwenming@ubuntu61-PowerEdge-R730:~$ !414
ps -f
UID         PID   PPID  C STIME TTY          TIME CMD
zhangwe+  97900  97899  0 19:18 pts/13   00:00:00 -bash
zhangwe+  98487  97900  0 22:09 pts/13   00:00:00 ps -f

命令别名:

alias命令是另一个shell的内建命令。命令别名允许你为常用的命令(及其参数)创建另一个名称,从而将输入量减少到最低。

要查看当前可用的别名,使用alias命令以及选项-p:

zhangwenming@ubuntu61-PowerEdge-R730:~$ alias -p
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'

可用使用alias命令创建属于自己的别名:

zhangwenming@ubuntu61-PowerEdge-R730:~$ alias li='ls -li'
zhangwenming@ubuntu61-PowerEdge-R730:~$ li
total 20
29163522 -rw-r--r-- 1 zhangwenming zhangwenming 8980  9月 19  2017 examples.desktop
29163545 drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月 24  2019 veridex
29163543 drwxrwxr-x 5 zhangwenming zhangwenming 4096  9月  1 17:28 workspace

要注意,因为命令别名属于内部命令,一个别名仅在它所被定义的shell进程中才有效。

四、使用Linux环境变量

1.什么是环境变量

bash shell用一个叫作环境变量的特性来存储有关shell会话和工作环境的信息。在bash shell中,环境变量分为两类:

  • 全局变量
  • 局部变量

全局环境变量

全局环境变量对于shell会话和所有生成的子shell都是可见的。局部变量则只对创建它们的shell可见。

要查看全局变量,可以使用env或printenv命令:

zhangwenming@ubuntu61-PowerEdge-R730:~$ printenv
HOME=/home/zhangwenming
...

要显示个别环境变量的值,可以使用printenv命令,但不要用env命令:

zhangwenming@ubuntu61-PowerEdge-R730:~$ printenv HOME
/home/zhangwenming
zhangwenming@ubuntu61-PowerEdge-R730:~$ env HOME
env: HOME: No such file or directory

也可以使用echo显示变量的值,在这种情况下引用某个环境变量的时候,必须在变量前面加上一个美元符($):

zhangwenming@ubuntu61-PowerEdge-R730:~$ echo $HOME
/home/zhangwenming

局部环境变量

局部环境变量只能在定义它们的进程中可见。

遗憾的是,在Linux系统并没有一个只显示局部环境变量的命令,set命令会显示为某个特定进程设置的所有环境变量,包括局部变量、全局变量以及用户自定义变量。

2.设置用户定义变量

设置局部用户定义变量

一旦启动了bash shell(或者执行一个shell脚本),就能创建在这个shell进程内可见的局部变量。可以通过等号给环境变量赋值,值可以是数值或字符串:

zhangwenming@ubuntu61-PowerEdge-R730:~$ echo $my_variable

zhangwenming@ubuntu61-PowerEdge-R730:~$ my_variable=HelloShell
zhangwenming@ubuntu61-PowerEdge-R730:~$ echo $my_variable
HelloShell

如果要给变量赋值一个含有空格的字符串值,必须单引号来界定字符串的首和尾:

zhangwenming@ubuntu61-PowerEdge-R730:~$ my_variable='Hello Shell'
zhangwenming@ubuntu61-PowerEdge-R730:~$ echo $my_variable
Hello Shell

设置了局部环境变量后,就能在shell进程的任何地方使用它了。但是,如果生成了另外一个shell,它在子shell中就不可用。

设置全局环境变量

在设定全局环境变量的进程所创建的子进程中,该变量都是可见的。创建全局环境变量的方法是先创建一个局部环境变量,然后在把它导出到全局环境中。这个过程通过export命令来完成,变量名前面不需要加$:

zhangwenming@ubuntu61-PowerEdge-R730:~$ my_variable="I am Global now"
zhangwenming@ubuntu61-PowerEdge-R730:~$ export my_variable
zhangwenming@ubuntu61-PowerEdge-R730:~$ bash
zhangwenming@ubuntu61-PowerEdge-R730:~$ echo $my_variable
I am Global now

修改子shell中全局环境变量并不会影响到父shell中该变量的值。子shell甚至无法使用export命令改变父shell中全局环境变量的值。

3.删除环境变量

可以用unset命令删除已经存在的环境变量,在unset命令中引用环境变量时,记住不要使用$:

zhangwenming@ubuntu61-PowerEdge-R730:~$ echo $my_variable
I am Global now
zhangwenming@ubuntu61-PowerEdge-R730:~$ unset my_variable
zhangwenming@ubuntu61-PowerEdge-R730:~$ echo $my_variable

如果你是在子进程中删除了一个全局环境变量,这只对子进程有效,该全局环境变量在父进程中依然可用。

4.数组变量

要给某个环境变量设置多个值,可用把值放在括号里,值与值之间用空格分隔:

zhangwenming@ubuntu61-PowerEdge-R730:~$ my_variable=(one two three)
zhangwenming@ubuntu61-PowerEdge-R730:~$ echo $my_variable
one
zhangwenming@ubuntu61-PowerEdge-R730:~$ echo ${my_variable[2]}
three
zhangwenming@ubuntu61-PowerEdge-R730:~$ echo ${my_variable[*]}
one two three
zhangwenming@ubuntu61-PowerEdge-R730:~$ my_variable[2]=ten
zhangwenming@ubuntu61-PowerEdge-R730:~$ echo ${my_variable[*]}
one two ten
zhangwenming@ubuntu61-PowerEdge-R730:~$ unset my_variable
zhangwenming@ubuntu61-PowerEdge-R730:~$ echo ${my_variable[*]}

五、理解Linux文件权限

1.Linux的安全性

Linux安全系统的核心是用户账户。每个能进入Linux系统的用户都会被分配唯一的用户账户。用户对系统中各种对象的访问权限取决于他们登录系统时用的账户。用户权限是通过创建用户时分配的用户ID(UserID,通常缩写为UID)来跟踪的。UID是数值,每个用户都有唯一的UID,但在登录系统时用的不是UID,而是登录名。登录名是用户用来登录系统的最长八字符的字符串(字符可以是数字或字母),同时会关联一个对应的密码。

/etc/passwd文件

zhangwenming@ubuntu61-PowerEdge-R730:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
zhangwenming:x:1009:1009:,,,:/home/zhangwenming:/bin/bash
...

字段包含了如下信息:

  • 登录用户名
  • 用户密码
  • 用户账户的UID(数字形式)
  • 用户账户的组ID(GID)(数字形式)
  • 用户账户的文本描述(称为备注字段)
  • 用户HOME目录的位置
  • 用户的默认shell

root用户账户是Linux系统的管理员,固定分配给它的UID是0。

/etc/shadow文件

/etc/shadow文件对Linux系统密码管理提供了更多的控制。只有root用户才能访问/etc/shadow文件,这让它比起/etc/passwd安全许多。/etc/shadow文件为系统上的每个用户账户都保存了一条记录。

2.使用Linux组

用户账户在控制单个用户安全性方面很好用,但涉及在共享资源的一组用户时就捉襟见肘了。为了解决这个问题,Linux系统采用了另外一个安全概念——组(group)。组权限允许多个用户对系统中的对象(比如文件、目录或设备等)共享一组共用的权限。每个组都有唯一的GID——跟UID类似,在系统上这是个唯一的数值。除了GID,每个组还有唯一的组名。

/etc/group文件

/etc/group文件包含系统上用到的每个组的信息:

zhangwenming@ubuntu61-PowerEdge-R730:~$ cat /etc/group
root:x:0:
zhangwenming:x:1009:
...

字段包含了如下信息:

  • 组名
  • 组密码
  • GID
  • 属于该组的用户列表

3.理解文件权限

使用文件权限符

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 8
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  2 01:47 NEW_ZWM
-rw-rw-r-- 1 zhangwenming zhangwenming   12  9月  2 23:49 test

输出结果的第一个字段就是描述文件和目录权限的编码。这个字段的第一个字符代表了对象的类型:

  • -代表文件

  • d代表目录

  • l代表链接

  • c代表字符型设备

  • b代表块设备

  • n代表网络设备

之后有3组三字符的编码。每一组定义了3种访问权限:

  • r代表对象是可读的
  • w代表对象是可写的
  • x代表对象是可执行的

若没有某种权限,在该权限位会出现单破折线。这3组权限分别对应对象的3个安全级别:

  • 对象的属主(设为登录名zhangwenming)
  • 对象的属组(设为组名zhangwenming)
  • 系统其他用户

默认文件权限

umask命令用来设置所创建文件和目录的默认权限:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ touch newfile
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -al newfile
-rw-rw-r-- 1 zhangwenming zhangwenming 0  9月  3 23:02 newfile
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ umask
0002

对文件来说,全权限的值是666(所有用户都有读和写的权限);而对目录来说,则是777(所有用户都有读、写、执行权限)。对于上例来说,文件的权限值为:666 - 002 = 664(文件属主有读和写权限;文件属组有读和写权限;其他用户有读权限)。

4.改变安全性设置

改变权限

chmod命令用来改变文件和目录的安全性设置。该命令的格式如下:

chmod options mode file

mode参数可以使用八进制模式或符号模式进行安全性设置。八进制模式设置非常直观,直接用期望赋予文件的标准3位八进制权限码即可:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 8
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  2 01:47 NEW_ZWM
-rw-rw-r-- 1 zhangwenming zhangwenming   12  9月  2 23:49 test
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ chmod 760 test
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -l
total 8
drwxrwxr-x 2 zhangwenming zhangwenming 4096  9月  2 01:47 NEW_ZWM
-rwxrw---- 1 zhangwenming zhangwenming   12  9月  2 23:49 test

符号模式的权限就没这么简单了,下面是在符号模式下指定权限的格式:

[ugoa...][+-=][rwxXstugo...]

第一组字符定义了权限作用的对象:

  • u代表用户
  • g代表组
  • o代表其他
  • a代表上述所有

第二组字符定义了对权限的操作:

  • +代表在现有权限基础上增加权限
  • -代表在现有权限基础上移除权限
  • =代表将权限设置成后面的值

第三组字符代表作用到设置上的权限,这个值要比通常的rwx多,额外的设置有:

  • X:如果对象是目录或者它已有执行权限,赋予执行权限
  • s:运行时重新设置UID或GID
  • t:保留文件或目录
  • u:设置属主权限
  • g:设置属组权限
  • o:设置其他用户权限
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ chmod o+r test
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -lF test
-rwxrw-r-- 1 zhangwenming zhangwenming 12  9月  2 23:49 test*
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ chmod u-x test
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ ls -lF test
-rw-rw-r-- 1 zhangwenming zhangwenming 12  9月  2 23:49 test

注意ls命令的-F选项,它能够在具有执行权限的文件名后加一个星号。

options为chmod命令提供了另外一些功能。-R选项可以让权限的改变递归地作用到文件和子目录。你可以使用通配符指定多个文件,然后利用一条命令将权限更改应用到这些文件上。

改变所属关系

Linux提供了两个命令来改变所属关系:chown命令用来改变文件的属主,chgrp命令用来改变文件的默认属组。

chown命令的格式如下:

chown options owner[.group] file

可用登录名或UID来指定文件的新属主:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ chown wuzebiao test

chown命令也支持同时改变文件的属主和属组:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ chown wuzebiao.zhangziliang test

可用只改变一个文件的默认属组:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ chown .wuzebiao test

如果你的Linux系统采用和用户登录名匹配的组名,可以只用一个条目就改变二者:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ chown wuzebiao. test

chown命令采用一些不同的选项参数。-R选项配合通配符可以递归地改变子目录和文件的所属关系。-h选项可以改变该文件的所有符号链接文件的所属关系。

注意:只有root用户能够改变文件的属主。任何属主都可以改变文件的属组,但前提是属主必须是原属组和目标属组的成员。

chgrp命令可以更改文件或目录的默认属组:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ chgrp wuzebiao test

用户账户必须是这个文件的属主,除了能够更换属组之外,还得是新组的成员。

5.共享文件

Linux为每个文件和目录存储了3个额外的信息位:

  • 设置用户ID(SUID):当文件被用户使用时,程序会以文件属主的权限运行。
  • 设置组ID(SGID):对文件来说,程序会以文件属组的权限运行;对目录来说,目录中创建的新文件会以目录的默认属组作为默认属组。
  • 黏着位:进程结束后文件还驻留(黏着)在内存中。

SGID位对文件共享非常重要。启用SGID位后,你可以强制在一个共享目录下创建的新文件都属于该目录的属组,这个组也就成为了每个用户的属组。SGID可通过chmod命令设置,它会加到标准3位八进制之前(组成4位八进制值),或者在符号模式下用符号s:

zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ mkdir testdir
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ chgrp wuzebiao testdir/
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ chmod g+s testdir/
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow$ cd testdir/
zhangwenming@ubuntu61-PowerEdge-R730:~/workspace/Tomorrow/testdir$ touch testfile

你可能感兴趣的:(Linux命令行)