Linux Command Line and Shell Scripting Bible
初识 Lniux Shell
Linux 的组成
Linux 的内核
Linux 内核主要负责:系统内存管理、软件程序管理、硬件设备管理、文件系统管理。
内核内存管理不仅管理物理内存,还要管理虚拟内存。
内核控制着 Linux 系统如何管理运行在系统上的所有进程,内核创建了第一个进程 init 来启动系统上所有其他进程。
内核管理硬件设备。任何需要与 Linux 系统进行通讯的设备都需要在 Linux 内核代码中加入其驱动程序代码。
驱动代码可以编译进内核,也可以将驱动代码模块插入内核而无需重新编译。Linux 下一切皆文件,硬件设备也被当作特殊的文件,设备文件分为每次处理一个字符的字符型设备文件,每次处理大块数据的块设备文件,以及数据包接发的网络设备文件。
内核采用虚拟文件系统作为和每个文件系统交互的接口。
GUN 工具
GUN 工具是 GNU 组织开发的一套完整的 Unix 工具。
其核心 GNU 工具包括处理文件、操作文本、管理进程的工具。
Shell 是一种特殊的交互式工具,Shell 的核心是命令行提示符,他允许你输入文本命令,解释命令并在内核中执行。
图形化桌面程序
X windows 系统是图形显示的核心部分,他是与显卡和显示器打交道的底层程序,目前最流行的软件包是 X.org 。
KDE 是 K Desktop Environment 桌面环境,GNOME 是 GNU Network Object Model Environement 。
基本的 bash shell 命令
帮助指令
Man
man man
man is the system's manual pager. Each page argument given to man is normally the name of a program, utility or function. The manual page associated with each of these arguments is then found and displayed. A section, if provided, will direct man to look only in that section of the manual. The default action is to search in all of the available sections following a pre-defined order (see DEFAULTS), and to show only the first page found, even if page exists in several sections.
Info
info info
The "Info" program described here is a stand-alone program, part of the Texinfo distribution, which is used to view Info files on a text terminal. "Info files" are typically the result of processing Texinfo files with the program 'makeinfo' (also in the Texinfo distribution).
文件系统
常见的 Linux 目录结构。
/bin:bin是Binary的缩写, 这个目录存放着最经常使用的命令。
/boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。
/dev :dev是Device(设备)的缩写, 该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。
*/etc:这个目录用来存放所有的系统管理所需要的配置文件和子目录。
/home:用户的主目录,在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。
/lib:这个目录里存放着系统最基本的动态连接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。
/lost+found:这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。
/media:linux 系统会自动识别一些设备,例如U盘、光驱等等,当识别后,linux会把识别的设备挂载到这个目录下。
/mnt:系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在/mnt/上,然后进入该目录就可以查看光驱里的内容了。
/opt:这是给主机额外安装软件所摆放的目录。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。
/proc:这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器:
/root:该目录为系统管理员,也称作超级权限者的用户主目录。
/sbin:s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序。
/srv:该目录存放一些服务启动之后需要提取的数据。
/sys:这是linux2.6内核的一个很大的变化。该目录下安装了2.6内核中新出现的一个文件系统 sysfs 。
sysfs文件系统集成了下面3种文件系统的信息:针对进程信息的proc文件系统、针对设备的devfs文件系统以及针对伪终端的devpts文件系统。
该文件系统是内核设备树的一个直观反映。
当一个内核对象被创建的时候,对应的文件和目录也在内核对象子系统中被创建。
/tmp:这个目录是用来存放一些临时文件的。
/usr:这是一个非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似于windows下的program files目录。
/usr/bin:系统用户使用的应用程序。
/usr/sbin:超级用户使用的比较高级的管理程序和系统守护程序。
/usr/src:内核源代码默认的放置目录。
/var:这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。
/run:是一个临时文件系统,存储系统启动以来的信息。当系统重启时,这个目录下的文件应该被删掉或清除。如果你的系统上有 /var/run 目录,应该让它指向 run。
浏览文件系统
ls - 列表命令
ls -F
可以在目录后显示/
,以区分文件和目录。
ls -a
显示隐藏文件。
ls -l
可以显示附加信息,效果等同于ll
。使用 ls -l *sh
可以进行正则匹配过滤要现实的内容。
tree - 树形目录 / 需要安装*
tree dir
展示该目录的树形目录结构。
cp - 复制命令
cp -i source destination
使用 -i
可以强制 shell 询问是否覆盖存在的文件。
cp -r source/ destination
递归复制文件夹。
ln - 链接文件
ln -s source destfilename
创建一个符号链接,符号连接可理解为 Windows 下的快捷方式,请勿为符号连接创建符号链接,复制后的符号链接还是一个符号链接。
ln source destfilename
创建一个硬链接,硬链接理解为源文件的另一个指针,注意,此时复制硬链接其实得到的不是硬链接的副本,而是直接复制了源文件。
mv - 移动文件或重命名
mv -i source dest
使用 -i
可以强制 shell 询问是否覆盖存在的文件。
mkdir - 创建文件夹
mkdir -p New_Dir
递归创建文件夹。
rm - 删除文件或文件夹
rmdir Empty_Dir
只能删除空文件夹。
rm -ri dir
递归删除文件夹,询问。
rm -rf
危险的命令!
file - 查看文件信息
file my_file
cat - 显示文本文件
cat -n file
每一行添加行号并显示。
cat -b file
有文本的每一行添加行号并显示。
sort - 排序显示
sort file
字典序排序
sort -n file
把数字当作数值排序
sort -M file
当作日期排序
sort -nr
降序输出
more - 分页显示
more file
less -less is more - 高级分页显示
less file
支持上下左右以及分页键。
tail/head - 显示文件尾部/头部
tail -fn 10 log
显示 log 文件后 10 行,并且实时显示更新内容。
更多的的 bash shell 命令
ps - 显示进程
ps -A
显示所有进程。
ps -u root
显示指定用户进程。
ps -ef
显示所有进程,以及详细信息。
ps -xf
显示进程树。
top - 实时进程监测
使用 f 和 s 修改排序方式,使用 d 修改刷新间隔,使用 q 退出。
kill - 给进程发送信号
kill -s KILL 7890
mount - 挂载储存媒体
umount - 卸载储存媒体
df - 查看挂载磁盘使用情况
df -h
用M和G作为单位
du - 显示特定目录下使用情况
du -h
用M和G作为单位
du -sh
显示标准单位的总计
grep - 搜索数据
grep str file
在文件中搜索字符串
grep -n str file
在文件中搜索字符串并显示所在行号
grep -c str file
在文件中搜索字符串并统计个数
理解Shell
/etc/passwd
设置默认的Shell类型
命令列表
(pwd;(echo $BASH_SUBSHELL))
使用小括号创建命令列表,命令列表就是使用括号包围起来的一组命令,它能够创建出子shell来执行这些命令。通过echo $BASH_SUBSHELL
环境变量可以看出当前子shell层数。
后台命令列表
命令 sleep 10
会将会话暂停10秒钟,然后返回shell CLI提示符,使用 & 符号将该子 shell 置入后台,让出 CLI ,通过 jobs -l
获取更多后台任务信息。同样的,我们可以在命令列表尾部加入 (sleep 2;echo $BASH_SUBSHELL;sleep 2)&
实现命令列表的后台运行,常用的有后台进行文件压缩。
协程 - coproc
coproc My_Job { sleep 10; }
创建协程名字 My_Job,执行命令 sleep 10。
只有在拥有多个协 程的时候才需要对协程进行命名,因为你得和它们进行通信。否则的话,让 coproc 命令 将其设置成默认的名字 COPROC 就行了。
coproc ( sleep 10; sleep 2 )
嵌套子进程。
内建命令
外部命令,有时候也被称为文件系统命令,是存在于bash shell之外的程序。通过 type -a command
获得命令详细信息,当外部命令执行时,会创建出一个子进程。这种操作被称为衍生(forking)。当进程必须执行衍生操作时,它需要花费时间和精力来设置新子进程的环境。所以说,外部 命令多少还是有代价的。
history - 历史命令
命令历史记录被保存在隐藏文件.bash_history中,它位于用户的主目录中。
bash命令的历史记录是先存放在内存中,当shell退出时才被写入到历史文件中。
可以在退出shell会话之前使用 history -a
强制将命令历史记录写入.bash_history文件。
.bash_history文件只有在打开首个终端会话时才会被读取。要想强制重新读 取.bash_history文件,更新终端会话的历史记录,可以使用 history -n
命令。
alias - 命令别名
ls='ls --color=auto
输入 ls
即等于 ls --color=auto
在定义好别名之后,你随时都可以在shell中使用它,就算在shell脚本中也没问题。要注意, 因为命令别名属于内部命令,一个别名仅在它所被定义的shell进程中才有效。
环境变量
环境变量储存在内存中,分为全局变量和环境变量,全局环境变量对于shell会话和所有生成的子shell都是可见的,而局部变量则只对创建它们的 shell可见。
printenv
可以显示当前的环境变量。
printenv HOME
等价于env HOME
等价于echo $HOME
显示全局变量HOME。
所有的环境变量名均使用大写字母,这是bash shell的标准惯例。 如果是你自己创建的局部变量或是shell脚本,请使用小写字母。变量名区分大小写。在涉及用户定义的局部变量 时坚持使用小写字母,这能够避免重新定义系统环境变量可能带来的灾难。
export - 导出环境变量
修改子shell中全局环境变量并不会影响到父shell中该变量的值。
子shell甚至无法使用export命令改变父shell中全局环境变量的值。
unset - 删除环境变量
PATH - 外部命令搜索目录
当你在shell命令行界面中输入一个外部命令时,shell必须搜索系统来找到对应 的程序。
在大多数发行版中,存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件。
数组变量
环境变量有一个很酷的特性就是,它们可作为数组使用。数组是能够存储多个值的变量。这 些值可以单独引用,也可以作为整个数组来引用。
mytest=(one two three four five)
echo $mytest 1
echo ${mytest[2]} three
echo ${mytest[*]} one two three four five
unset mytest[2]
注意,此时的三号位并不会被后面的数据补齐,而是空。
Linux 文件权限
useradd - 添加用户
默认情况下,useradd命令不会创建HOME目录,但是-m命令行选项会使其创建HOME目录,并将/etc/skel目录中的文件复制了过来。
userdel - 删除用户
默认情况下,userdel命令会只 删除/etc/passwd文件中的用户信息,而不会删除系统中属于该账户的任何文件。
如果加上-r参数,userdel会删除用户的HOME目录以及邮件目录。
usermod - 修改用户
除此之外,还有另外 一些可能派上用场的选项。
usermod -l
修改用户账户的登录名。
usermod -L
锁定账户,使用户无法登录。
usermod -p
修改账户的密码。
usermod -U
解除锁定,使用户能够登录。
usermod -L选项尤其实用。它可以将账户锁定,使用户无法登录,同时无需删除账户和用户的数据。 要让账户恢复正常,只要用-U选项就行了。
passwd chpasswd - 修改密码
如果只用passwd命令,它会改你自己的密码。系统上的任何用户都能改自己的密码,但只 有root用户才有权限改别人的密码。
-e选项能强制用户下次登录时修改密码。你可以先给用户设置一个简单的密码,之后再强制 在下次登录时改成他们能记住的更复杂的密码。
chpasswd命令能从 标准输入自动读取登录名和密码对(由冒号分割)列表,给密码加密,然后为用户账户设置。你 也可以用重定向命令来将含有userid:passwd对的文件重定向给该命令。
chpasswd < users.txt
文件权限符
这个字段的第一个字符代表了对象 的类型:-代表文件、d代表目录、l代表链接、c代表字符型设备、b代表块设备、n代表网络设备。
之后有3组三字符的编码。每一组定义了3种访问权限:r代表对象是可读的、w代表对象是可写的、x代表对象是可执行的。这三组分别是属主、属组、任意用户权限。
chmod - 改变文件或目录的安全设置
chown - 改变文件或目录的属主
chgrp - 改变文件或目录的属组
管理文件系统
文件系统日志方法
数据模式:索引节点和文件都会被写入日志;丢失数据风险低,但性能差
有序模式:在顺序模式中,只有元数据被记录到日志中,但在日志被标记为提交前,数据会被写入文件系统。在这种模式下,如果在增大文件时,数据还未写入就发生崩溃,那么在恢复时这个事务会被简单的撤销,文件保持原来的状态;在性能和安全性之间取得了良好的折中
回写模式:在回写模式中,只有元数据被记录到日志中,数据会被直接写入主文件系统。这种模式能提供较好的性能,不过有较大的风险。例如:在增大文件时,数据还未写入就发生崩溃,那么文件系统恢复后,文件后面就可能出现垃圾数据。
写时复制(copy-on-write,COW)
如果要修改数据,会使用克隆或可写快照。修改过的数据 并不会直接覆盖当前数据,而是被放入文件系统中的另一个位置上。即便是数据修改已经完成, 之前的旧数据也不会被重写。
构建基础脚本
在创建shell脚本文件时,必须在文件的第一行指定要使用的shell。其格式为:
#!/bin/bash
变量
value1=10 value2=$value1
给value2赋value1的值。
命令替换
反引号字符(`)
将命令输出赋值给变量 testing='date'
。
命令替换是由子shell完成的,由该子shell所执行命令是无法使用脚本中所创建的变量的,如果你使用的是内建的shell命令,并不会涉及子shell。
重定向输入和输出
>
覆盖输出到目标文件
>>
追加数据
管道(|)
Linux系统实际上会同时运行管道两端的命令,在系统内部将它们连接起来。在第一个命令产生输出的同时,输出会被立即送给第二个命令。数据 传输不会用到任何中间文件或缓冲区。
数学运算($[ operation ])
bash shell数学运算符只支持整数运算。要使用浮点运算就要使用 bc 即 bash shell 内建的计算器。
使用结构化命令
bash shell的if语句会运行if后面的那个命令。如果该命令的退出状态码是0 (该命令成功运行),位于then部分的命令就会被执行,fi语句用来表示if-then 语句到此结束。
在 elif 语句中, 紧跟其后的 else 语句属于 elif 代码块。 它们并不属于之前的 if-then 代码块。
如果不写test命令的condition部分,它会以非零的退出状态码退出,并执行else语句块。
数值比较方法,注意 bash shell 无法处理浮点数。
字符串使用大小于号比较必须转义,否则会被识别为重定向语句。
在比较测试中,大写字母被认为是小于小写字母的。但sort命令恰好相反。当你将同样的 字符串放进文件中并用sort命令排序时,小写字母会先出现。这是由各个命令使用的排序技术 不同造成的。
检测目录是否存在。
检查文件是否存在。
检查文件是否有数据。
检查文件是否可写。
检查文件是否可执行。
数学表达式支持。
正则表达式支持。
case 语句支持。
更多的结构化命令
按空格遍历字符串。
拼接字符串。
用户输入
bash shell会将一些称为位置参数(positional parameter)的特殊变量分配给输入到命令行中的 所有参数。这也包括shell所执行的脚本名称。位置参数变量是标准的数字:$0
是程序名,$1
是第一个参数,$2
是第二个参数,依次类推,直到第九个参数$9
。在第9个变量之后,你必须在变量数字周围加上花括号,比如${10}
。
basename命令会返回不包含路径的脚本名。
特殊变量$#
含有脚本运行时携带的命令行参数的个数。
通过使用for命令遍历这两个特殊变量,你能看到它们是如何不同地处理命令行参数的。$*
变量会将所有参数当成单个参数,而$@
变量会单独处理每个参数。这是遍历命令行参数的一个绝妙方法。
引用
本作品采用知识共享署名 4.0 国际许可协议(CC BY-NC-SA 4.0)进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,可适当缩放并在引用处附上图片所在的文章链接。
最后更新于