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你的机器:

    echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
  • /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 内建的计算器。

使用结构化命令

if command
then 
    commands
else
    commends
fi

bash shell的if语句会运行if后面的那个命令。如果该命令的退出状态码是0 (该命令成功运行),位于then部分的命令就会被执行,fi语句用来表示if-then 语句到此结束。

if command1
then
    command
elif command2
then
    command
elif command3 
then
    command
elif command4 
then
    command
fi

在 elif 语句中, 紧跟其后的 else 语句属于 elif 代码块。 它们并不属于之前的 if-then 代码块。

if test condition 
then 
    commands 
fi

如果不写test命令的condition部分,它会以非零的退出状态码退出,并执行else语句块。

if [ $value1 -eq $value2 ]

数值比较方法,注意 bash shell 无法处理浮点数。

if [ $str1 \> $str2 ]

字符串使用大小于号比较必须转义,否则会被识别为重定向语句。

在比较测试中,大写字母被认为是小于小写字母的。但sort命令恰好相反。当你将同样的 字符串放进文件中并用sort命令排序时,小写字母会先出现。这是由各个命令使用的排序技术 不同造成的。

if [ -d $directory ]

检测目录是否存在。

if [ -f $file_name ]

检查文件是否存在。

if [ -s $file_name ]

检查文件是否有数据。

if [ -w $file_name ]

检查文件是否可写。

if [ -x $file_name ]

检查文件是否可执行。

if (( expression ))

数学表达式支持。

if [[ expression ]]

正则表达式支持。

case variable in 
pattern1 | pattern2) commands1;; 
pattern3) commands2;; 
*) default commands;; 
esac

case 语句支持。

更多的结构化命令

for var in list 
do 
    commands
done

按空格遍历字符串。

list="Alabama Alaska Arizona Arkansas Colorado" list=$list" Connecticut"

拼接字符串。

用户输入

bash shell会将一些称为位置参数(positional parameter)的特殊变量分配给输入到命令行中的 所有参数。这也包括shell所执行的脚本名称。位置参数变量是标准的数字:$0是程序名,$1是第一个参数,$2是第二个参数,依次类推,直到第九个参数$9。在第9个变量之后,你必须在变量数字周围加上花括号,比如${10}

basename命令会返回不包含路径的脚本名。

特殊变量$#含有脚本运行时携带的命令行参数的个数。

通过使用for命令遍历这两个特殊变量,你能看到它们是如何不同地处理命令行参数的。$*变量会将所有参数当成单个参数,而$@变量会单独处理每个参数。这是遍历命令行参数的一个绝妙方法。

引用

本作品采用知识共享署名 4.0 国际许可协议(CC BY-NC-SA 4.0)进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,可适当缩放并在引用处附上图片所在的文章链接。

最后更新于