介绍
类Unix操作指的是类似Unix操作系统的一大类操作系统,包括了个人电脑主流的Mac OS和服务器主流的Linux系统(如Ubuntu、Fedora、CentOS等发行版)。
个人电脑上使用类Unix系统时也可以很方便地使用图形界面(graphical user interface; GUI),但是使用服务器时基本只能使用其命令行(command-line interface; CLI)。即使是在个人电脑上,命令行的使用效率也显著高于图形界面的使用。
因此,尽管学习命令行需要花费一些时间和精力,但是在熟练掌握命令行之后,工作效率能够得到显著提升。
本文介绍最常用的一些命令行使用方法。不同的系统的命令可能略有不同,这里介绍Mac OS和Ubuntu。
操作命令行一般使用终端(terminal)应用。
如果使用Mac OS,可以从Spotlight搜索中寻找Terminal应用并打开。
如果使用Ubuntu,可以搜索terminal并打开、或使用快捷键Ctrl+Alt+t。也可以使用Ctrl+Alt+F1进入字符终端界面,但是不再能操作图形界面。Ctrl+Alt+F7可以回到图形界面。
如果远程登录,一般来说直接进入终端。
路径(path)
路径可以代表对应Windows文件夹的目录(directory)或普通文件(file)。
目录可以包含0个或至少1个文件。
用户始终在某个目录下工作,称为工作目录(working directory)。
路径分为绝对路径(absolute path)和相对路径(relative path),其中绝对路径表示该路径表示一个确定的目录或文件,与工作目录无关;相对路径是相对于工作目录定义的,代表了该路径与工作目录的关系。
特殊的路径包括:
- /,根目录(root),是所有路径的起点。
- ~,home目录(home directory),对于不同的用户(user)可能不同,由于对于同一个用户确定,也可以作为绝对路径的起点。一般来说,~的值为/Users/<username>或/home/<username>。
- .,当前目录(current directory)。
- ..,父目录(parent directory),指当前目录的上一级目录,常用来定义相对路径。/的父目录为/。
从一个路径进入下一级路径只需要加入/<目录或文件名>。
/Users/admin ├── dir1 │ ├── dir3 │ └── file1 ├── dir2 └── file2
假设~为/Users/admin,其中包含了dir1和dir2两个目录和file2文件,dir2为空目录,dir1含有一个空目录dir3和一个文件file1。
则dir1的绝对路径为/Users/admin/dir1,dir2的绝对路径为/Users/admin/dir2,dir3的绝对路径为/Users/admin/dir1/dir3,file1的绝对路径为/Users/admin/dir1/file1。
若工作目录为/Users/admin/dir1,则..为/Users/admin,../dir2为/Users/admin/dir2,dir3为/Users/admin/dir1/dir3,file1为/Users/admin/dir1/file1。
Q:若工作目录为dir3,则dir2相对于工作目录的相对路径是什么?
权限
每个文件有自己的权限(permission),包括了用户属主(owner)、属组(group)、其它用户(other users)的读(read)、写(write)、执行(execute)三种权限。
例如可能对于某个用户建立的txt文件,属主只有读、写权限,属组和其它用户只有读权限。
那么所有人都可以阅读文件内容,但是只有属主可以修改文件。
命令
一个命令的形式为:
$ 命令名 -选项 参数
这里我们用"$ "$表示终端提示(prompt),命令名是命令的名称,帮助计算机寻找该命令对应的程序,一般是一个英文单词,-选项(flag)是可选(optional)的选项,可以改变命令的效果,参数(argument)是该命令需要的参数取值。以python为例:
$ python
表示打开python的交互式界面。
$ python main.py
表示使用python运行main.py程序,并在终端显示输出。
$python -i main.py
为交互式(interactive)选项,表示运行main.py程序并进入python的交互式界面。
有时需要在一个命令前面加上sudo使其以超级用户(superuser)即root权限运行。
若对于一个命令的使用有疑问,可以通过man命令进行查询。如man python显示了python命令的说明文档。
命令之间可以使用;或&&链接,表示第一个命令完成后执行第二个命令。
重复上一个命令可以使用!!,一般结合sudo使用。重复上一个以v开头的命令可以使用!v。
$ pwd /Users/admin $ !! /Users/admin $ ls dir1 dir2 file2 $ !p /Users/admin $ chmod a+x file2 chmod: illegal option -- - $ sudo !! # sudo执行上述命令 Password:
下文假设工作目录为/Users/admin,且file1包含一行"This is file 1.",file2包含一行"This is file 1."。
/Users/admin ├── dir1 │ ├── dir3 │ └── file1: This is file 1. ├── dir2 └── file2: This is file 2.
文件系统
命令 | 例子 |
---|---|
ls 列出目标目录下的所有内容 可以选择的选项有:
参数为目标目录,可以是绝对/相对目录。缺失时默认为当前目录.。 |
$ ls dir1 dir2 file2 $ ls dir1 dir3 file1 $ ls -a dir1 . .. dir3 file1 $ ls -R dir1 dir3 file1 dir1/file3: $ ls /Users/admin # 绝对路径 dir1 dir2 file2 $ ls .. # 相对路径:上一级目录 playground $ ls -hal total 8 drwxr-xr-x 5 admin admin 170B Jul 8 18:27 . drwx------+ 178 admin admin 5.9K Jul 8 14:06 .. drwxr-xr-x 4 admin admin 136B Jul 8 18:27 dir1 drwxr-xr-x 2 admin admin 68B Jul 8 18:05 dir2 -rw-r--r-- 1 admin admin 16B Jul 8 18:27 file2 第一列显示了文件/目录的权限,从左到右一次为:
|
cd 将工作目录改为目标目录。 参数为目标目录,可以是绝对/相对目录。 |
$ cd dir1 # 转移到dir1 $ ls dir3 file1 $ ls .. dir1 dir2 file2 $ cd ../dir2 # 转移到dir2 $ cd - # 回到上一次所在的目录,即dir1 $ ls dir3 file1 |
pwd 打印工作目录。 |
$ pwd /Users/admin $ cd dir2 $ pwd /Users/admin/dir2 |
touch 参数是该文件的路径,若已经存在,会改变文件的上次读取时间;否则,会建立空文件。 |
$ touch file2 # 改变file2的上次读取时间 $ touch file3 # 新增文件file3 $ ls dir1 dir2 file2 file3 |
mkdir 建立目标目录。 可选选项为-p,表示若目标目录的任何一个中间目录(intermediate directory)不存在,则建立该目录。 参数为目标目录。 |
$ mkdir dir4 # 建立dir4 $ mkdir -p dir5/dir6 # 建立dir5,并建立dir5/dir6 |
rm 删除目标目录/文件。 可选选项为-r,表示递归地删除,用来删除文件。 参数为目标目录/文件。 使用时需小心误删重要文件! |
$ rm dir2 # 不能直接删除目录 rm: dir2: is a directory $ ls dir1 dir2 file2 $ rm -r dir2 $ ls dir1 file2 $ touch tmp # 建立新文件tmp $ rm tmp # 删除tmp $ mkdir tmp # 建立空目录tmp $ rmdir tmp # rmdir可以删除空目录 |
cp 将原文件/目录复制到目标路径。 可选选项-r表示复制目录。 参数有两个,分别为原文件/目录,和目标路径。 |
$ cp file2 file3 # 将file2复制到file3 $ ls dir1 dir2 file2 file3 $ cp dir2 dir4 # 需要使用-r选项 cp: dir2 is a directory (not copied). $ cp -r dir2 dir4 $ ls dir1 dir2 dir4 file2 file3 |
mv 类似cp,但是删除原目录/文件,即移动目录/文件。 不需要使用-r选项即可移动目录。 |
$ mv file2 file3 # 将file2重命名为file3 $ mv dir2 dir4 $ ls dir1 dir4 file3 |
文件信息
命令 | 例子 |
---|---|
cat 打印一个或多个文件内容。 参数可以为一个或多个文件名。 |
$ cat file2 This is file 2. $ cat dir1/file1 file2 This is file 1. This is file 2. |
head 打印文件的前count行。count的默认值为10。 可选选项为-n count,表示打印前count行。 参数为一个或多个文件名。 |
首先新建文件tmp并且在前10行分别输入$1, 2, \ldots, 10$。 $ head -n 1 tmp 1 $ head -n 2 tmp file2 ==> tmp <== 1 2 ==> file2 <== This is file 2. |
tail 类似head,打印文件的后count行。 |
首先新建文件tmp并且在前10行分别输入$1, 2, \ldots, 10$。 $ tail -n 2 tmp 9 10 |
less 分屏显示文件内容。是一个很方便的快速查看文件的方式。 按Ctrl+u向上滚动、Ctrl+d向下滚动、q退出。 |
$ less file2 # 查看file2的内容 |
wc 统计文件的行数/单词数/字符数。 可选选项有:
参数为文件。 |
$ wc -l file2 # 行数 1 file2 $ wc -w file2 # 单词数 4 file2 $ wc -m file2 # 字符数 16 file2 |
diff 比较两个文件的内容。 参数为第一个文件名和第二个文件名。 "< "后的内容为第一个文件多出来的行。 "> "后的内容为第二个文件多出来的行。 两个文件相同的行不会显示。 |
$ diff dir1/file1 file2 1c1 < This is file 1. --- > This is file 2. |
sort 对文件内容进行排序输出。默认排序方式为按照字典序(alphabetical order)升序排列。 可选选项有:
|
建立一个tmp文件,前三行内容分别为1, 2, 10。 $ sort tmp 1 10 2 $ sort -n tmp 1 2 10 $ sort -r tmp 2 10 1 $ sort -nr tmp 10 2 1 |
grep 在文件/目录中查找模式(pattern)出现的行。 可选选项为-R表示递归地在文件/目录中查找,-l表示只显示文件名。 第一个参数为模式的字符串,可以使用正则表达式。 第二个参数为文件/目录所在的路径。 |
$ grep "This" * grep: dir1: Is a directory grep: dir2: Is a directory file2:This is file 2. $ grep -l "This" * grep: dir1: Is a directory grep: dir2: Is a directory file2 $ grep -R "This" . ./dir1/file1:This is file 1. ./file2:This is file 2. $ grep -R "[0-9]*" . ./dir1/file1:This is file 1. ./file2:This is file 2. |
权限管理
命令 | 例子 |
---|---|
chown 改变文件/目录的权限。 可选选项为-R表示递归地更改整个文件/目录。 第一个参数为权限改动方式,第二个参数为文件/目录的所在路径。 第一个参数可以是一个8进制的数字,也可以在u/g/o/a选择一个分别代表属主/属组/其他人/所有人、在+/-/=选择一个分别代表增加/减少/设为、在r/w/x选择一个分别代表可读/可写/可执行。 |
$ ls -hal file2 -rw-r--r-- 1 admin admin 16B Jul 8 19:12 file2 $ sudo chmod u+x file2 # 给属主加上可执行权限 $ sudo chmod o-r file2 # 给其他人去除可读权限 $ ls -hal file2 -rwxr----- 1 admin admin 16B Jul 8 19:12 file2 $ sudo chmod a+rw file2 # 给所有人家上可读和可写权限 $ ls -hal file2 -rwxrw-rw- 1 admin admin 16B Jul 8 19:12 file2 $ sudo chmod 0777 file2 # 八进制数0777对应0111111111,即所有人都有所有权限 $ ls -hal file2 -rwxrwxrwx 1 admin admin 16B Jul 8 19:12 file2 $ sudo chmod 0644 file2 # -rw-r--r--即0110100100对应八进制数0644 -rw-r--r-- 1 admin admin 16B Jul 8 19:12 file2 |
chown/chgrp 改变文件的所有者(owner)/用户组(group)。 可选选项为-R表示递归地改变整个文件/目录。 第一个参数为新的所有者/用户组,第二个参数为文件/目录的路径。 |
$ ls -hal file2 -rw-r--r-- 1 admin admin 16B Jul 8 19:12 file2 $ sudo chown root file2 $ ls -hal file2 -rw-r--r-- 1 root admin 16B Jul 8 19:12 file2 $ sudo chgrp netusers file2 $ ls -hal file2 -rw-r--r-- 1 root netusers 16B Jul 8 19:12 file2 |
其它命令
命令 | 例子 |
---|---|
which 命令本身是一个可执行的文件,因此也存在于文件系统的某个路径下。 which可以查找命令所在的路径。 参数为命令名。 |
$ which sort /usr/bin/sort $ which which which: shell built-in command |
zip 压缩文件/目录 可选选项-r表示递归地压缩文件/目录。 参数为压缩后的zip文件的路径以及一个或多个文件/目录。 |
$ zip a.zip file2 # 将file2压缩为a.zip $ zip -r a.zip * # 将当前目录压缩为a.zip |
unzip 解压zip文件。 可选选项为
|
$ touch tmp1 tmp2 tmp3 $ zip a.zip tmp* $ unzip -v a.zip Archive: a.zip Length Method Size Ratio Date Time CRC-32 Name -------- ------ ------- ----- ---- ---- ------ ---- 0 Stored 0 0% 07-08-18 21:59 00000000 tmp1 0 Stored 0 0% 07-08-18 21:59 00000000 tmp2 0 Stored 0 0% 07-08-18 21:59 00000000 tmp3 -------- ------- --- ------- 0 0 0% 3 files $ unzip a.zip Archive: a.zip replace tmp1? [y]es, [n]o, [A]ll, [N]one, [r]ename: N $ unzip -n a.zip Archive: a.zip $ unzip -o a.zip Archive: a.zip extracting: tmp1 extracting: tmp2 extracting: tmp3 $ unzip -d tmp a.zip Archive: a.zip extracting: tmp/tmp1 extracting: tmp/tmp2 extracting: tmp/tmp3 |
tar 压缩/解压缩文件/目录。 可选参数较多,一般用-czvf进行压缩,用-xzvf进行解压缩。 压缩时,需要提供后缀为tar.gz的压缩文件路径和一个或多个文件/目录的路径。 解压缩时,需要提供tar.gz压缩文件路径。可选地,可以加上-C和解压到的目录。 |
$ touch tmp1 tmp2 tmp3 $ tar -czvf a.tar.gz tmp* a tmp1 a tmp2 a tmp3 $ mkdir tmp $ tar -xzvf a.tar.gz -C tmp x tmp1 x tmp2 x tmp3 $ ls tmp tmp1 tmp2 tmp3 |
wget 下载URL地址对应的文件。 参数为URL地址。 |
$ wget www.dscademy.com/index.php # 下载dscademy主页 |
ping 检测与目标机器网络是否联通。 可选参数为-c表示发送包数,默认无限次发送直到Ctrl+c终止。 |
$ ping -c 10 www.dscademy.com PING dscademy.com (107.180.41.245): 56 data bytes 64 bytes from 107.180.41.245: icmp_seq=0 ttl=43 time=259.548 ms 64 bytes from 107.180.41.245: icmp_seq=1 ttl=43 time=262.591 ms 64 bytes from 107.180.41.245: icmp_seq=2 ttl=43 time=686.698 ms 64 bytes from 107.180.41.245: icmp_seq=3 ttl=43 time=259.871 ms 64 bytes from 107.180.41.245: icmp_seq=4 ttl=43 time=831.470 ms 64 bytes from 107.180.41.245: icmp_seq=5 ttl=43 time=613.915 ms 64 bytes from 107.180.41.245: icmp_seq=6 ttl=43 time=956.347 ms 64 bytes from 107.180.41.245: icmp_seq=7 ttl=43 time=258.060 ms 64 bytes from 107.180.41.245: icmp_seq=8 ttl=43 time=258.481 ms 64 bytes from 107.180.41.245: icmp_seq=9 ttl=43 time=260.027 ms --- dscademy.com ping statistics --- 10 packets transmitted, 10 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 258.060/464.701/956.347/264.536 ms |
shutdown/reboot 关机/重启 |
$ sudo shutdown -h +5 "this system will be reboot after 5 minutes" # 5分钟后关机 Shutdown at Sun Jul 8 22:26:31 2018. shutdown: [pid 86218] $ sudo reboot # 现在重启 |
history 查看历史命令。 |
$ ls $ history | tail -n 1 930809 ls |
open/xdg-open 在Mac/Linux中使用正确的(图形界面)应用打开一个文件/目录。 |
$ open dir1 # 使用Finder/nautilus打开dir1目录 $ touch a.py; open a.py # 使用Xcode/IDLE打开a.py $ touch index.html; open index.html # 使用Chrome/Firefox打开index.html |
多命令结合
命令行中的命令的输出除了直接打印在控制台(console)内,还可以选择打印在文件里或作为下一个命令的输入。
前者的方式是在命令的结尾加上>或>>和文件名。
例如echo "hello"的效果是输出"hello",如果接上> tmp则将删除tmp所有内容,并且写入其输出,即"hello";如果接上>>,则不删除原来内容,加上"hello"。
$ echo "hello" > tmp && cat tmp hello $ echo "hello" >> tmp && cat tmp hello hello $echo "hello" > tmp && cat tmp hello
后者称为管道(pipe)。其作用是将前面命令的输出作为后面命令的输入。
例如可以将cat的结果作为head的输入。
$ echo "1\n2\n3" > tmp && cat tmp | head -n 2 | tail -n 1 2
另外还可以使用脚本语言,如bash、Python、perl进行更复杂的编程完成任务,这里限于篇幅不做介绍。
安装外部软件
类Unix系统安装软件可以使用图形界面的资源中心,也可以使用更方便的命令行工具。
Mac OS可以使用homebrew软件,成功安装后使用brew install <包名>即可安装包。
下载使用Ruby:
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Ubuntu可以使用apt-get命令,例如
$ sudo apt-get install python-pip
安装Python的包管理器pip。
编程
类Unix系统上编程非常方便,这里讲解几个Python和C++的例子。
第一个例子是一个不需要用户输入的程序。
再来看一个需要用户输入一个整数N,程序会打印N + 1的例子。
如果输入不是用户手动输入,而是来自一个文件,或者一个命令的输出,则需要用到上一节的管道(pipe)。
我们来看一个既需要用户输入又需要命令行参数的例子。
更改默认配置
终端应用启动前,会自动执行一个文件,一般来说是~/.bash_profile。
因此,如果有一些配置,希望计算机始终保持,可以在该文件里加入相应的内容。
终端在执行一个命令的时候,会在全局变量$PATH中遍历并寻找是否有可执行文件的名字和该命令名字相同,如果存在,执行该文件。
例如/usr/bin属于$PATH变量中,sort存在/usr/bin/目录下,因此终端可以找到/usr/bin/sort这个文件并执行。
加入用户新写了一个工具mysort,并且存在了~/program/目录下,希望在终端内输入mysort命令时,可以执行~/program/mysort文件。
那么可以使用export将~/programs加在$PATH中,并且存入~/.bash_profile文件。
假设用户希望将向google发送10次包的命令
ping -c 10 www.google.com
存成一个方便的快捷键fping,那么可以使用别名(alias)。
~/.bash_profile如下:
export PATH=$PATH:~/programs/ alias fping="ping -c 10 www.google.com"
那么每次开机或者登录的时候,这两个配置都会自动执行,进而可以直接使用mysort和fping两个命令。
远程登录
远程登录服务器或笔记本电脑时,使用图形界面不再方便。
此时使用本文的各种命令行工具即可完成各类任务。
本节讲解服务器的登录和文件在本地和服务器之间的转移。
登录服务器使用的标准命令是ssh,其用法如下:
ssh -p 22 root@107.180.41.245
可以以root身份登录IP地址为107.180.41.245,端口(port)为22的机器,需要输入对应的密码。
登陆后,就可以类似于本机打开终端一样地操作远程机器。
传输文件的命令是scp,其用法如下:
scp -P 22 ~/program/mysort root@107.180.41.245:/home/admin/program/
可以将本机的~/program/mysort文件上传到服务器的/home/admin/program/目录下。
更方便的一个命令是sftp,首先登录远程服务器。
sftp -P 22 root@107.180.41.245
sftp> lls # 本地执行ls program sftp> lcd program # 本地执行cd sftp> lls mysort sftp> ls # 远程执行ls program sftp> cd program # 远程执行cd sftp> put mysort # 将本地的mysort文件上传到远程的工作目录 sftp> get mysort # 将远程的mysort文件上传到本地的工作目录
为了避免重复地输入密码,可以使用如下方法跳过密码验证步骤。
$ ssh-keygen -t rsa -b 4096 # 生成RSA的公钥(public key)和私钥(private key); 无需输入文件和passphrase,直接按回车即可 Generating public/private rsa key pair. Enter file in which to save the key (/Users/admin/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /Users/admin/.ssh/id_rsa. Your public key has been saved in /Users/admin/.ssh/id_rsa.pub. The key fingerprint is: SHA256:??????????????????????????????????????????? admin@localhost The key's randomart image is: +---[RSA 4096]----+ |?????????????????| |?????????????????| |?????????????????| |?????????????????| |?????????????????| |?????????????????| |?????????????????| |?????????????????| |?????????????????| +----[SHA256]-----+ $ ssh-copy-id -i ~/.ssh/id_rsa.pub root@107.180.41.245 # 将公钥上传到服务器
软件推荐
这里推荐一些提高办公效率的软件/工具。
- tmux:一款分屏工具,适合笔记本和服务器电脑使用。
- autojump:输入路径的大致名称即可直接将工作目录转为该路径。例如,"j program"命令可以直接跳转到~/program目录。
更多面试问题见面试真题汇总