Shell是什么

上图来自Unix编程圣经《APUE》英文第二版。如图,处于最中心的是操作系统内核,负责机器硬件资源管理,进程管理等;shell,函数库(值得记住的是C标准函数库)和某些应用程序均直接构建于内核之上,属于同一层。内核与这层的交互是通过以C风格定义的系统函数进行的,即图中灰色部分。系统函数完全屏蔽了内核的实现细节。

Shell 是指一种应用程序,这个应用程序提供了一个界面,专门用来读取用户输入的命令,解析并执行命令,用户通过这个界面访问操作系统内核的服务。

Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。

我们基础阶段课程前两天学习的命令都是shell命令,至于shell编程的部分则在就业班部分学习。

Shell 的种类

shell可以分成两类:

第一类是由Bourneshell衍生出来的包括sh、ksh、bash、zsh等;

第二类是由Cshell衍生出来的,包括csh与tcsh等。

当前比较通用的shell就是bashshell

查看当前shell种类

终端上键入echo $SHELL
/bin/bash

为什么要学习Shell命令

shell作为用户和操作系统内核之间的信使。如果我们想要让操作系统高效的帮用户进行数据处理,就需要和信使shell进行沟通并掌握和信使的沟通技巧。
因此了解信使的性格(操作命令)是尤为必要的。

重要概念

通配符

? 通配一个任意字符

* 通配多个任意字符

Inode

Inode是linux/unix操作系统中的一种数据结构,包含了各文件相关的一些重要信息。在创建文件系统时,就会同时创建大量的inode。

与Inode相关的还有一个概念就是inumber,Inumber只是文件相关信息中的一项信息。
Inode是指的数据结构结点,而inumber结点对应的索引编号。

文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector)。每个扇区储存512字节(相当于0.5KB)。
操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个"块"(block)。这种由多个扇区组成的"块",是文件存取的最小单位。"块"的大小,最常见的是4KB,即连续八个 sector组成一个 block。
文件数据都储存在"块"中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。
每一个文件都有对应的inode,里面包含了与该文件有关的一些信息。
都包含了哪些主要信息呢?

Inode的结构:

inode编号[inumber]
用来识别文件类型,以及用于 C函数 stat 的模式信息
文件的链接数目  [ln -s ]
属主的 UID
属主的组 ID (GID)
文件的大小
文件所使用的磁盘块的实际数目
最近一次修改的时间

1、一个文件只对应一个Inode,而一个文件根据其大小,会占用多块blocks。
2、当我们删除文件的时候,只是把Inode标记为可用,文件在block中的内容是没有被清除的,只有在有新的文件需要占用block的时候,才会被覆盖。

表面上,用户通过文件名,打开文件。实际上,系统内部这个过程分成三步:首先,系统找到这个文件名对应的inode号码;其次,通过inode号码,获取inode信息;最后,根据inode信息,找到文件数据所在的block,读出数据。

软链接与硬链接

软链接

pc@iZ25g2i2xsmZ:~/code$ ls -i
786883 a.c 786866 test 786890 test.o
pc@iZ25g2i2xsmZ:~/code$ ls -i a.c
786883 a.c
pc@iZ25g2i2xsmZ:~/code$
pc@iZ25g2i2xsmZ:~/code$ ln -s a.c a

pc@iZ25g2i2xsmZ:~/code$ ls -ail

total 28
786851 drwxrwxr-x 2 pc pc 4096 Dec 15 17:01 .
786702 drwxr-xr-x 4 pc pc 4096 Dec 15 16:57 ..
792212 lrwxrwxrwx 1 pc pc    3 Dec 15 17:01 a -> a.c
786883 -rw-rw-r-- 1 pc pc   71 Dec 14 14:31 a.c
786894 -rw-rw-r-- 1 pc pc    0 Dec 15 16:58 .aout
786866 -rwxrwxr-x 1 pc pc 8557 Dec 14 14:31 test
786890 -rw-rw-r-- 1 pc pc 1504 Dec 14 14:31 test.o

硬链接

软硬有何不同

硬链接是不会占用磁盘的空间的。
如果说删除硬链接的话,就会改变Inode count的数量。硬链接还有其他的两个特性:不能跨Filesystem也不能link目录。

下面再来看看这个软链接

[root@yufei test]# ls -il testfile.soft testfile
976 -rw-r--r--. 3 root root 0 Apr 5 21:50 testfile
978 lrwxrwxrwx. 1 root root 8 Apr 5 21:52 testfile.soft -> testfile
他的Inode number和原文件不一样。而且大小也发生了变化。可见,这个软链接是重新建立了一个文件,而文件是指向到原文件,而不是指向原Inode。当然他会占用掉 inode 与 block。当我们删除了源文件后,链接文件不能独立存在,虽然仍保留文件名,但我们却不能查看软链接文件的内容了。

但软链接是可以跨文件系统,而且是可以链接目录。他就相当于windows系统下的快捷方式一样。通过这个特性,我们可以通过软链接解决某个分区inode conut不足的问题(软链接到另一个inode count足够多的分区)。

重定向

**分类:输入重定向 < 、输出重定向 > 、追加输出重定向 >>

把/dev/null看作"黑洞". 它非常等价于一个只写文件. 所有写入它的内容都会永远丢失. 而尝试从它那儿读取内容则什么也读不到.

cat /dev/null > /var/log/messages

将执行命令产生的错误信息重定向到 黑洞中表示忽略。

管道

管道也是一种文件,在同一个管道中数据只能单向流动。

管道操作符 '|',它只能处理经由前面一个指令传出的正确输出信息,对错误信息信息没有直接处理能力。然后,传递给下一个命令,作为标准的输入.

注意:管道命令只处理前一个命令正确输出,不处理错误输出;

比如

ls -al | wc -l 统计ls -al 命令的结果集的行数。

文件系统

相对路径

路径是对目录的层次结构的一种描述。我们想要进入到某个目录下,那从当前路径到目标路径一定有一条 路径是可以到达的。
相对路径描述的路径是从当前所在出发目录的方法。

绝对路径

同理,绝对路径描述的路径是从根目录/开始的路径。

根目录/

Linux目录结构的来源

Linux目录结构的来源于UNIX目录结构

http://lists.busybox.net/pipermail/busybox/2010-December/074114.html

PDP-7计算机介绍

https://en.wikipedia.org/wiki/PDP-7

话说1969年,Ken Thompson和Dennis Ritchie在小型机PDP-7上发明了Unix。1971年,他们将主机升级到了PDP-11。

当时,他们使用一种叫做RK05的储存盘,一盘的容量大约是1.5MB。

没过多久,操作系统(根目录)变得越来越大,一块盘已经装不下了。于是,他们加上了第二盘RK05,并且规定第一块盘专门放系统程序,第二块盘专门放用户自己的程序,因此挂载的目录点取名为/usr。也就是说,根目录"/"挂载在第一块盘,"/usr"目录挂载在第二块盘。除此之外,两块盘的目录结构完全相同,第一块盘的目录(/bin, /sbin, /lib, /tmp...)都在/usr目录下重新出现一次。
后来,第二块盘也满了,他们只好又加了第三盘RK05,挂载的目录点取名为/home,并且规定/usr用于存放用户的程序,/home用于存放用户的数据。
从此,这种目录结构就延续了下来。随着硬盘容量越来越大,各个目录的含义进一步得到明确。
  /:存放系统程序,也就是At&t开发的Unix程序。
  /usr:存放Unix系统商(比如IBM和HP)开发的程序。
  /usr/local:存放用户自己安装的程序。
  /opt:在某些系统,用于存放第三方厂商开发的程序,所以取名为option,意为"选装"。

重要技能

键入shell命令的时候能够擅用Tab键自动补齐

常用shell命令

ls

list,列举当前目录下的文件列表(包括目录)
常用选项
a 显示所有文件(目录、默认隐藏不显示的.打头的文件)
l 详细信息
i 显示iNode编号(iNumber)

# 后面不加任何参数表示 匹配任何条件

python@ubuntu:~$ ls
class    Documents  examples.desktop  Pictures  Templates  workspace
Desktop  Downloads  Music             Public    Videos

# 查找以D字符开始的文件和目录
python@ubuntu:~$ ls D*
Desktop:

Documents:

Downloads:
node-v6.1.0-linux-x64

pwd

Print Working Directory,打印当前工作目录

pc@iZ25g2i2xsmZ:~/code$ pwd
/home/pc/code

cd

change directory,改变当前的工作目录

. 代表当前路径  
..代表上一级路径  
/ 代表根目录  
~ 代表当前用户的主目录\(home directory,家目录\)

pc@iZ25g2i2xsmZ:~/code$ cd ..
pc@iZ25g2i2xsmZ:~$ pwd
/home/pc

cd 后面不跟参数默认的是切换到用户的主目录

cd 想切换到的目录
pc@iZ25g2i2xsmZ:~$ ls
code code1
pc@iZ25g2i2xsmZ:~$ cd code
pc@iZ25g2i2xsmZ:~/code$ ls
a.c test test.o

查看文件内容

cat、more、less、tail、head

cat
英文单词 catenate的缩写,释义 vt.连接,使连续;
从文件(可能多个)中读取数据并且输出 内容。复制文件(多个)内容到一个新的文档中用于合并或者追加。

more
一次显示一屏幕的文本内容,只能往后。

从第三行开始显示myfile文件
more +3 myfile.txt

显示以
more +/"hope" myfile.txt

less
一次显示一屏幕的文本内容,可以往前、往后。

head

head表示头部,表示查看文件的前n行,n默认为10。
pc@iZ25g2i2xsmZ:~/test_struct$ head ii

bbbbbbbb
cccccccc
dddddddd
eeeeeeee
ffffffff
gggggggg
hhhhhhhh
iiiiiiii
jjjjjjjj

如果想自定义查看行数。

pc@iZ25g2i2xsmZ:~/test_struct$ head -5 ii
bbbbbbbb
cccccccc
dddddddd
eeeeeeee

tail

tail表示尾部,表示查看文件的后n行,n默认为10。

pc@iZ25g2i2xsmZ:~/test_struct$ tail ii
qqqqqqqq
rrrrrrrr
ssssssss
tttttttt
uuuuuuuu
vvvvvvvv
wwwwwwww
xxxxxxxx
yyyyyyyy
zzzzzzzz

如果想自定义查看行数。
pc@iZ25g2i2xsmZ:~/test_struct$ tail -5 ii
vvvvvvvv
wwwwwwww
xxxxxxxx
yyyyyyyy
zzzzzzzz

文件(目录)操作

cp、mv、mkdir、rmdir、rm

cp

copy,表示复制的意思。 将当前目录下的main.c文件复制到上一级目录中
pc@iZ25g2i2xsmZ:~/code$ cp main.c ../

也可以在复制文件的过程中进行改名
pc@iZ25g2i2xsmZ:~$ cp test_file i

也可以进行交互式的复制(在目标文件存在的时候会进行提醒是否覆盖)
pc@iZ25g2i2xsmZ:~$ cp test_file i -i
cp: overwrite ‘i’? y

目录是一种文件,所以也可以复制目录 但是需要加-R选项
pc@iZ25g2i2xsmZ:~$ cp -R code code1

也可以在复制的时候带上过滤条件
pc@iZ25g2i2xsmZ:~$ cp code/*.c test/ -r

mv

move,表示移动、剪切的意思。 移动指定文件 t.tar 到指定目录 test下
pc@iZ25g2i2xsmZ:~$ mv t.tar test/

对文件进行改名
pc@iZ25g2i2xsmZ:~$ mv my.tar your.tar

同理也可以移动目录
pc@iZ25g2i2xsmZ:~$ mv code1 test/

也可以在移动目录的时候进行改名
pc@iZ25g2i2xsmZ:~$ mv test tt

mkdir
创建目录 make directory

-p选项 在创建多层级目录的时候,如果父 目录结点不存在mkdir将首先创建。
Creates the directory /home/chope/a/b/c. If the parent directory /home/chope/a/b does not already exist, mkdir will create that directory first.

mkdir -p /home/chope/a/b/c

rmdir remove directory

删除目录目录 ,前提是目录为空,否则将删除失败。

rm
单词 remove的缩写 ,表示删除、移除的意思。
可以用于删除文件(目录), removes (deletes) files or directories.。

-r (--recursive) 递归-
-i 交互
-f 强制的 忽略一切

rm myfile.txt
rm -f myfile.txt
rm *

这是一个容易带来灾难的命令,使用之前请三思再下手。

若是重要数据的销毁,绝对要提一下这个命令。
和rm不同的时候,shred命令会对删除的进行覆盖重写,一般使用 shred -u -z filename

2017年初rm -rf 惨案:GitLab丢了300GB实时产品数据

一位身处荷兰的GitLab系统管理员在进行数据库复制过程中不小心在一台错误的服务器上删除了一个目录,他删除了一个包含 300GB 实时产品数据的文件夹,在取消 rm -rf 删除命令后该文件夹只剩下 4.5GB 数据。并且最近的数据还是在6小时前备份的。 (移步灾祸现场)[http://top.jobbole.com/36129/]

更改文件权限与所属

chmod

英文 change mode的缩写。在Linux(或者类UNIX系统)上,有一套规则 谁能能够访问那些文件,以及他们能如何访问。
这种规则就叫文件权限(file permissions or file modes)。
chmod提供了方法可以用于改变规则。

permissions defines the permissions for the owner of the file (the "user"), members of the group who owns the file (the "group"), and anyone else ("others"). There are two ways to represent these permissions: with symbols (alphanumeric characters), or with octal numbers (the digits 0 through 7).

每一组权限定义了 文件拥有者(user),文件拥有者同组用户(group),其他用户(other)。
有两种方式方式权限:

字母数字字符

pc@iZ25g2i2xsmZ:~$ ll test_file 
-rwxrw-r-- 1 pc pc 10 Dec 20 15:09 test_file

rwxrw-r-- 可以看出

user 对于该文件can **r**ead,can **w**rite,can e**x**ecute。
group对于该文件can **r**ead,can **w**rite
other对于该文件can **r**ead

相对的方式设置权限
优点
直接简单,只需要关注目标和现在之间的差距进行操作即可。
缺点
如果差距较多 可能进行的操作很复杂
chmod g+wx,o+w test_file

绝对的方式来设置权限 可以忽略当前的权限设置
chmod u=rwx,g=rx,o=r test_file

八进制数
数字法设置权限比较直接。比如 chmod 754 myfile
10进制就是满10进1位,每一位上的数有0、1、2、3、4、5、6、7、8、9
8进制就是满 8进1位,每一位上的数有0、1、2、3、4、5、6、7

权限为上的每个8进制数 比如7都是由三个比特位上的值x权值的乘积之和
一个8进制数由3个bit位构成
421

000
001
010
011
100
101
110
111

4 stands for "read",
2 stands for "write",
1 stands for "execute"

八进制数7就是4_1+2_1+1_1构成的,也即 rwx。
八进制数6就是4_1+2_1+1_0构成的,也即 rw-。

那八进制数3 表示的权限是什么?

权限对于目录的影响

pc@iZ25g2i2xsmZ:~/workspace$ ll
total 10812
drwxrwxr-x  8 pc pc     4096 Apr 23 23:11 ./
drwxr-xr-x  5 pc pc     4096 Mar 25 21:53 ../
-rw-rw-r--  1 pc pc     1344 Mar 24 23:21 00_read_tar_filedata_len.c
-rwxrwxr-x  1 pc pc     9559 Mar 25 09:51 a.out*
drwxrwxr-x  2 pc pc     4096 Jan  4 13:03 boxuegu/
drwxrwxr-x 10 pc pc     4096 Mar 24 23:20 class/
drwxrwxr-x  8 pc pc     4096 Mar 25 23:55 code/
drwxrwxr-x  2 pc pc     4096 Mar 24 17:40 crazyc/
dr-xr-xr-x  2 pc pc     4096 Mar 25 11:07 gdb/
-rw-rw-r--  1 pc pc      165 Mar 25 09:50 hello.c
-rw-rw-r--  1 pc pc 11018240 Mar 25 23:56 tar_project.tar
drwxrwxr-x  2 pc pc     4096 Apr 23 23:11 tt/
pc@iZ25g2i2xsmZ:~/workspace$ chmod a-w tt 
pc@iZ25g2i2xsmZ:~/workspace$ ll
total 10812
drwxrwxr-x  8 pc pc     4096 Apr 23 23:11 ./
drwxr-xr-x  5 pc pc     4096 Mar 25 21:53 ../
-rw-rw-r--  1 pc pc     1344 Mar 24 23:21 00_read_tar_filedata_len.c
-rwxrwxr-x  1 pc pc     9559 Mar 25 09:51 a.out*
drwxrwxr-x  2 pc pc     4096 Jan  4 13:03 boxuegu/
drwxrwxr-x 10 pc pc     4096 Mar 24 23:20 class/
drwxrwxr-x  8 pc pc     4096 Mar 25 23:55 code/
drwxrwxr-x  2 pc pc     4096 Mar 24 17:40 crazyc/
dr-xr-xr-x  2 pc pc     4096 Mar 25 11:07 gdb/
-rw-rw-r--  1 pc pc      165 Mar 25 09:50 hello.c
-rw-rw-r--  1 pc pc 11018240 Mar 25 23:56 tar_project.tar
dr-xr-xr-x  2 pc pc     4096 Apr 23 23:12 tt/
pc@iZ25g2i2xsmZ:~/workspace$ cd tt/
pc@iZ25g2i2xsmZ:~/workspace/tt$ touch a.c
pc@iZ25g2i2xsmZ:~/workspace/tt$ ll
total 8
dr-xr-xr-x 2 pc pc 4096 Apr 23 23:12 ./
drwxrwxr-x 8 pc pc 4096 Apr 23 23:11 ../
-rw-rw-r-- 1 pc pc    0 Apr 23 23:13 a.c
pc@iZ25g2i2xsmZ:~/workspace/tt$ mv a.c b.c
mv: cannot move ‘a.c’ to ‘b.c’: Permission denied
pc@iZ25g2i2xsmZ:~/workspace/tt$ rm a.c
rm: cannot remove ‘a.c’: Permission denied
pc@iZ25g2i2xsmZ:~/workspace/tt$ touch aaa
touch: cannot touch ‘aaa’: Permission denied

chown

使用基本形式 chown [OPTION]... [OWNER][:[GROUP]] FILE...

改变file.txt文件所属用户为chope
chown chope file.txt

如果我想改变一个目录下的所有文件呢? -R选项
chown -R chope /files/work

在工作场景中需要经常碰到这样一个场景,手动将某目录下的所有子目录和文件全部给 属于某个组的一个用户
chown -R orancle:oinstall /usr/path/data/

查找文件 find

-name pattern Returns true if the base of a file name (the path with the leading directories removed) matches shell pattern pattern. The metacharacters ('*', '?', and '[ ]') match a '.' at the start of the base name. To ignore a directory and the files under it, use -prune; see an example in the description of -path. Braces are not recognised as being special, despite the fact that some shells including Bash imbue braces with a special meaning in shell patterns. The filename matching is performed with the use of the fnmatch library function. Don't forget to enclose the pattern in quotes in order to protect it from expansion by the shell.
查找 根目录下及其子目录下 所有的C源代码文件。

find / -name *.C

查找 /usr/bin /usr/lib目录下的zip压缩文件

find /usr/bin /usr/lib -name 'zip'

-iname 忽略文件名大小写

-size [-|+] n [cwbkMG]根据文件大小查找文件

b for 512-byte blocks (this is the default if no suffix is used)
c for bytes
w for two-byte words
k for Kilobytes (units of 1024 bytes)
M for Megabytes (units of 1048576 bytes)
G for Gigabytes (units of 1073741824 bytes)

大于2MB的
find / -name *.zip -size +2M

小于2G的
find / -name *.zip -size -2G

等于
find / -name *.zip -size 2K

-type
Returns true if a file is of type c:
d directories目录文件
f regular files普通文件
l symbolic links.链接文件

查找文件内容grep

grep是一套工具,在Linux系统中有多种实现。

tar

-f选项后面跟上归档文件名称,所以一般都放置在参数列表的最后一个。

tar -zcvf /tmp/etc.tar.gz /etc 打包后以 gzip 压缩

tar -jcvf /tmp/etc.tar.bz2 /etc 打包后,以 bzip2 压缩

gzip/gunzip命令

gzip命令只能将一个文件压缩成一个.gz压缩包,并且不保留原文件。

pc@iZ25g2i2xsmZ:~/code/project$ ls 01test_compress.c a.gz gzjoin.c mygzip.h tuixiangzi 02_compress_gz.c a.out libz.a pcgzip zconf.h 03_gz.c compress2.data Makefile shuangseqiu zlib.h 04_gzgetc.c compress.data migong tgzip pc@iZ25g2i2xsmZ:~/code/project$ gzip .c pc@iZ25g2i2xsmZ:~/code/project$ ls 01test_compress.c.gz a.gz gzjoin.c.gz mygzip.h tuixiangzi 02_compress_gz.c.gz a.out libz.a pcgzip zconf.h 03_gz.c.gz compress2.data Makefile shuangseqiu zlib.h 04_gzgetc.c.gz compress.data migong tgzip pc@iZ25g2i2xsmZ:~/code/project$ gunzip .gz pc@iZ25g2i2xsmZ:~/code/project$ ls 01test_compress.c a gzjoin.c mygzip.h tuixiangzi 02_compress_gz.c a.out libz.a pcgzip zconf.h 03_gz.c compress2.data Makefile shuangseqiu zlib.h 04_gzgetc.c compress.data migong tgzip

如果想保留源文件且进行(解)压缩这么操作

pc@iZ25g2i2xsmZ:~/code/project$ gzip -c mygzip.h > mygzip.h.gz
pc@iZ25g2i2xsmZ:~/code/project$ ls
01test_compress.c  a               libz.a    mygzip.h.gz  tuixiangzi
02_compress_gz.c   compress2.data  Makefile  pcgzip       zconf.h
03_gz.c            compress.data   migong    shuangseqiu  zlib.h
04_gzgetc.c        gzjoin.c        mygzip.h  tgzip

由于zip不能将多个源文件压缩并且合并为一个文件,但是tar却能将多个文件归档为一个文件。所以在这种情况下先用tar进行归档 然后使用压缩工具gzip进行压缩。

虽然有诸如 cat file1 file2 | gzip > foo.gz等命令可以达到这个目的但是且无法再解压的时候分离出两个文件。

进程管理ps top kill

切换sudo su exit

sudo command可以让命令在root权限下运行而不用切换至root用户。
前提是 该用户属于sudoer,否则失败。

su [-] [用户名]
-代表切换用户的时候默认进入该用户的主目录;如果在切换的时候不带- 则不会切换目录。
用户名为你想切换到的用户。
用户名如果不写,默认切换到root用户。
root用户可以切换到任何用户。

网络ifconfig

主要用于查看用户当前计算机的各个网卡相关信息(网络IP地址、子网掩码等等)

参考资料

包括但不限于
http://www.computerhope.com/unix.htm

Linux命令行常用快捷键

Ctrl+a:光标回到命令行首。 (a:ahead) Ctrl+e:光标回到命令行尾。 (e:end) Ctrl+l:清屏,光标到第一行。

一个实用的shell脚本

#!/bin/bash
n=1
echo "检查xxx服务..."
while true
do
        if test $n -gt 20
        then 
                echo "xxx服务启动失败"
                break
        fi

        sleep 5
        n=$(($n+1))
        port=`netstat -antp | grep "0.0.0.0:8080"`
        if [ ${#port} -gt 3 ]; then
                echo "xxx服务已经启动"
                break;
        fi
done

bash的历史