第三章 基本的bash shell命令
3.3 bash手册
man keyword / keyword -help
3.4浏览文件系统
cd
相对路径,绝对路径,当前目录,父目录 ,根目录
.. . ./ ~
- -返回进入此目录之前所在的目录
ls
- -d仅展示目录名,而不展示目录下的内容列表
- -F 区分 文件夹和文件
- -R 递归子目录和子文件
- -l 展示详细信息
- -a 显示隐藏 文件
- -i 显示系统为文件分配的唯一编号 inode 编号
- script_name:过滤,可以配合通配符 * ? 使用
- --time=atime:显示的事件为访问时间而非更改时间。
3.6 处理文件
创建 touch
- -a 只改变访问时间,不更改修改时间
复制 cp source destination
- -i是否覆盖已有文件
- destination可以是地址+文件名 也可以只有地址。但注意只有地址的时候,目录的最后一定加上/。避免最后一级文件在复制前其实并不存在的情况,在这种情况,将会复制一个与文件目录最后一级同名的文件。
- 单点'.'在复制文件这里很适合用于将其他目录的文件复制到当前目录下
cp /etc/NetworkManager/NetworkManager.conf .
- -R:递归地复制整个目录
链接文件
- ln -s data_file ln_data_file 符号链接,ln_data_file为独立的文件,拥有不同的修改时间,并且有不同于原文件的大小
- ls -i data_file ln_data_file 硬链接,拥有相同的编号,文件大小,修改时间
- 硬链接只能在同一储存媒体创建。
- 不要创建链接文件的链接文件,应该选择对原文件创建链接文件,一面连接链错乱。
移动或重命名文件:mv
- mv a b a和b在同一个目录,名字不同则为重命名。 ab目录不同则为移动目录,移动目录的文件名字也可以不同,此时既移动了目录,也更改了名字。
3.6删除文件:rm
- -i确认是否要删除该文件
- -f不受提示影响,强制删除文件
- -r 递归
3.7 处理目录
3.7.1创建目录 mkdir
- -p连续创建多个父子连接的目录 mkdir parent_floder/child_floder
3.7.2 删除目录
- rmdir:删除空目录
- rm -r 删除文件夹内的文件后,再删除文件夹
- -rm -rf 强制删除文件夹及其中内容,且无提示
3.8查看文件内容
3.8.1查看文件类型 file
3.8.2 查看整个文件
1) cat
- -n 显示行号
- -b 只给有文本内容的行加上行号
- -T 不显示制表符效果,使用^I替换所有制表符
more/lsee - 空格翻页,回车下一行。
- 可退出形式的查看部分文件:more/less(less提供更多功能)
3.8.3查看部分文件:tail/head
tail/head file_name:显示最后/开头10行
tail -n num 显示最后num行文本
第四章 更多的bash shell 命令
4.1检测程序
4.1.1 探查进程 ps
- 默认只展示运行在当前控制台下属于当前用户的进程。
ps的3中命令行参数类型:Unix, BSD, GNU 单破折线/无破折线/双破折线 - a 全部进程
- l 长列表
4.1.2事实监测进程 top
4.1.3结束进程
kill命令
kill [pid]
killall命令:通过进程名来识别需要结束的任务
kill process_name 可以使用通配符
4.2监测磁盘空间
第6章 使用Linux环境变量
6.1 什么是环境变量
用于储存有关shell会话和工作环境的信息
分为全局变量和局部变量
6.1.1全局环境变量
- 所有的shell以及其子shell都是可见的。
- printenv/env 不带参数可以查看所有的全局变量
- printenv env_var / env $env_var 可以展示指定环境变量的内容
6.1.2局部环境变量
- 没有单独变量用于展示局部环境变量,set用于展示包含全局和局部环境变量。
6.2设置用户定义变量
6.2.1 设置局部用户定义变量
- 赋值 my_variable='zz' 注意整个语句不能有空格,否则会将第一个空格前的内容解释为shell命令。提示command not found
- 引用 my_variable
- 局部变量一般使用小写,全局变量使用大写
- 自定义变量只在当前shell可用,不可在其余shell(包含该shell的子shell或父shell)
6.2.2设置全局环境变量
- 先建立全局变量,再把它导入到全局变量中
$ my_variable='zz'
$ export my_variable
$ #此时的变量将可以在子shell中使用
- 更改子shell中的全局变量,不影响其他shell中该变量的值。
6.3 删除环境变量 uset
unset my_variable #注意不需要$符号
- 在子进程中删除了一个全局环境变量,父进程中该全局环境变量不受影响。
6.4默认的shell环境变量
参见本书的p111表 6-1
6.5设置PATH环境变量
- 作用系统会搜索在PATH环境变量包含的目录,这些文件夹下的可执行文件,可以不指定路径而直接以文件名执行。
- 查看 echo $PATH
- 添加PATH环境变量
$ PATH=$PATH:/home/ubuntu/Scripts
- 若当前的工作目录需要加入PATH环境变量
$ PATH=$PATH:. #直接以.代表当前目录即可
- 本节定义的变量只能持续到退出或系统重启
6.2定义系统环境变量(让环境变量持久化)
- 启动文件/环境文件: 当登入Linux系统启动一个bash shell时,bash会朝招几个文件中的命令。这些文件被称为启动文件/环境文件
- 启动bash shell有三种方式,下面为三种方式的启动文件的介绍。(登录时作为默认登录shell/作为非登录shell的交互式shell/作为运行脚本的非交互式shell)
6.6.1 登录shell
以下五个启动文件
- /etc/profile
- $HOME/.bash_profile
- $HOME/.bash_login
- $HOME/.profile
- $HOME/.bashrc
1)/etc/profile
系统上默认的bash shell的主启动文件。系统上的每个用户登录时都会执行。
- 使用for循环运行/etc/profile.d目录下的所有文件。
if [ -d /etc/profile.d ]; then for i in /etc/profile.d/*.sh; do if [ -r $i ]; then . $i fi done unset i
2) 其余4个$HOME目录下的启动文件
- 提供一个用户专属的启动文件来定义该用户所用到的环境变量,大多数Linux发行版只使用这其中的一到两个。
shell会按照顺序运行前三个文件,如果其中一个被运行,余下的则被忽略。 - $HOME/.bash_profile
- $HOME/.bash_login
- $HOME/.profile
6.6.2 交互式shell进程
如果不是登录系统是启动的,则称为交互式shell。
则不会访问/etc/profile启动文件,只会访问HOME目录中的.bashrc文件。(这就是为什么在配置Jupyter notebook的时候,将相关路径加入~/.bashrc而非上方的3个文件)
6.6.3非交互式shell
- 系统执行脚本时使用的shell。它没有命令行提示符。
- BASH_ENV用于这种情况下,运行一些特定启动的命令。
- 如果没有设置BASH_ENV,shell脚本可以继承并使用父shell中已经设置并且导出的变量。
6.6.4 环境变量持久化
方法:将变量放入环境变量。
- /etc/profile 可能随着发行版的升级而更新覆盖,自定义的变量将失效
- 在/etc/profile.d中新建一个.sh文件。把所有修改/定义的变量放入这个文件。系统启动运行etc/profile时将运行这里的sh文件。
- 大多数发行版中,使用~/.bashrc储存永久性bash shell文件。但如果设置了BASH_ENV变量,如果BASH_ENV没有指向~/.bashrc,那么将不会生效。
6.7数组变量
$ # 括号中 空格分隔
$ myarr=(one two three)
$ #使用索引来引用对应的值
$ echo $(myarr[1])
$ #查看整个数组 索引值改为星号
$ #使用unset来删除数组的值。
第7章 理解Linux文件权限
7.1 Linux的安全性
- uid 登录名-密码
7.1.1 /etc/passwd
包含以下内容
- 用户登录名
- 用户密码(默认显示为x)
- 用户账户的uid
- 用户账户的组ID
- 用户账户的文本描述
- 用户HOME目录的位置
- 用户的默认shell
7.1.2 /etc/shadow文件
用于管理用户的密码以及密码有效期限的文件
- 登录名
- 加密后的密码
- 自上次修改密码后过去的天数密码
- 多少天后才能更改密码
- 多少天后必须更改密码
- 密码过期前多少天提醒用户更改密码
- 密码过期后多少天禁用用户账户
- 用户账户被禁用的日期
- 预留字段
7.1.3 添加新用户 useradd
- m 新建HOME目录
$ useradd -m test
7.1.4 删除用户 userdel
- r 删除用户的HOME目录以及邮件目录
$ userdel -r test
7.1.4 用户修改
1. usermod
- -l 修改登录名
- -L 锁定账户
- -p 修改账户的密码
- -U 解除锁定,使用户能够登陆。
2. passwd和chpasswd
passwd:更改单个用户密码
- e 下次登录必须更改密码
$ passwd test
$ #会让重复输入两次密码以更改该用户密码
chpasswd:使用标准文件批量更改用户密码
文件每行为 userid:passwd
3. chsh, chfn和change
7.2使用Linux组
7.2.1 /cat/group文件
- 组名
- 组密码
- GID
- 属于该组的用户列表
当一个用户在/etc/passwd文件中指定某个组为默认组时,用户账户不会作为该组成员再出现在/etc/group文件中。
当一个用户同时是多个组中的成员时,在/etc/passwd文件中记录的是用户所属的主组,也就是登录时所属的默认组,而其他组称为附加组。
7.2.2 创建新组
groupadd 创建无用户新组
$ groupadd groupname
usermod 往新组添加用户
- g 更改用户的默认组
- G添加该组到用户的属组的列表里,不会影响默认组
$ user -G/g shared test
7.2.3修改组 groupmod
- -n 修改组名
- -g 修改组id
$ groupmod -n new_name shared
7.3 理解文件权限
7.3.1使用文件权限符
ls -l 展示的第一个字段就是描述文件和目录权限的编码。
第一个字符描述了类型
- 文件
- d目录
- l链接
- c代表字符型设备
- b代表块设备
- n代表网络设备
之后有3组字符的编码。分别为属主/属组/系统的其他用户。
每个组内的权限包含3类rwx,若某个位置为-则表示没有该种权限。
7.3.2 默认文件权限
umask 查看新建文件的默认权限。
umask 返回4位数字。第一位为黏着位
后3位分别代表3个属的文件权限
但注意umask是返回的掩码,新建文件的默认权限实际上是使用全权限值(文件666目录777)减去umask值(8进制的计算)。比如若umask 为026,那么文件的默认权限为640(rw-r-----)。
7.4 改变安全性设置
7.4.1改变权限:chmod
- 格式chmod options mode file
- mode分为两种:八进制模式和符号模式
1)选项option
- -R配合file的通配符,递归的将权限操作应用于多个文件和子目录。
2)八进制模式
chmod 760 file
3)符号模式
[ugoa][+-=][rwxXstugo]
3各参数分别表示
- 用户组
- 增减等于
- 要应用的权限
$ chmod o+r file #对所有三个属 增加 r(读取权限)
$ chmod g-x file #对属组用户移除执行权限
7.4.2 改变所属关系
1) chown 改变文件属主
chown options owner[.group] file
$ chown dan newfile #改变文件属主
$ chown dan.shared newfile #改变文件的属主(dan)和属组(shared)
$ chown .shared new file #只改变文件的默认属组
$ chown test. newfile #如果Linux采用和用户登录名匹配的组名,在属主后加.,可以同时改变属主和属组
- 只有root用户可以改变用户的属主,任何属主都可以改变用户的属组,只要属主属于更改前后两个属组的成员。
2) chgrp改变文件的默认属组
chgrp shared newfile
第9章 安装软件程序
- PMS(package management system):曝光李系统
- 基于Debian的发行版(如Ubuntu和Linux Mint)使用dpkg命令
- 基于Red Hat的发行版(Fedora,openSUSE)使用rmp命令
- 书本介绍了两种,仅总结dpkg的aptidue命令。
- aptitude 和 apt-get/cache的比较
9.2 基于Debian的系统
用aptitude管理软件包
aptitude
- show pkgname :查看包信息
- install pkgname:安装包
- remove pkgname:移除包
- search pkgname:不完全匹配方式搜索包
- 展示所有匹配的包
- 包名前的i表示已安装。vp表示可安装
- purge pkgname:移除包以及相关的配置文件和文件夹
- safe-upgrade:安全升级全部包
- full-upgrade/dist-upgrade:稍激进的升级策略
dpkg - -L pkgname 展示这个已安装包的全部文件
- -search absolute_file_name 展示这个绝对文件路径属于的包
aptitude仓库
清单地址:/etc/apt/sources.list
第10章 使用编辑器
第11章 构建基本脚本
11.2创建shell脚本文件
基本脚本实例
#!/bin/bash
date
who
- 井号后的内容为注释,不会进行运行。
- 在脚本目录下直接以脚本名运行,如果该目录不在环境变量PATH内,将无法找到该可执行文件。可以通过添加至$PATH或使用./script_name的方式来运行。
- 新创建的问价你如果用户没有执行权限,需要新增用户对文件的执行权限。
$ chmod u+x file_name
11.3显示消息:echo
- 如果需要展示双引号/单引号,那么使用单引号/双引号来划定字符串。
- -n 将文本字符串和命令输出显示在同一行
$ echo "who is running this:"
$ who
11.4使用变量
11.4.1使用环境变量
- 使用美元符号引用
- 可以在双引号中引用
- 如果需要展示美元符号$而非引用变量,可以使用反斜杠进行反转义。
- ${}也是常见的变量引用方式,花括号用于帮助系统识别变量名。
11.4.2用户变量
- 组成:字母,数字,下划线
- 区分大小写
- 系统会自动决定变量的数据类型
- 变量在对应的shell脚本的结束前将一直有效
- 与系统变量的引用方式一致。
- 定义举例
var1=10
var2=testing
var3="more params"
11.4.3 命令替换
将b命令的输出赋值给b变量。
- 反引号符和$()格式
$testing=`date`
$testing=${date}
11.5 重定向输入和输出
11.5.1 输出重定向
指定输出的接收
$ date > receive_file
- >> 两个大于号,表示追加而非替换,当receive_file存在时
$ who >> receive_file
11.5.2 输入重定向
将文件的内容重定向到命令。
- 普通输入重定向
$ wc < test6
2 11 6
# wc 直接接文件名,将会多返回一个字符串--文件名
$wc test6
2 11 6 test6
- 内联输入重定向:使用命令行而非文件来输入字符。开始和结尾使用相同的符号囊括内容。
$ wc << EOF
>wuliking
>jung un
>EOF
2 2 16
11.6 管道
- 使用管道符号 “|”拼接多个命令,前一个命令的输出将作为后一个命令的输入。
- 下方的命令会以more的方式展示sort后的file_name文件的内容
$ cat file_name|sort|more
11.7 执行数学运算
11.7.1 expr命令
$ expr 1 + 5
6
$ expr 1 * 4
expr: syntax error
$ expr 1 \* 4
4
11.7.2 方括号
$ var1=$[1 + 5]
$ echo $var1
6
# 不赋值或不是用echo命令,直接写方括号表达式将报错
$ $[1 + 2]
3: command not found
# 因为算式的结果直接输入,将3作为命令解释
- 星号也不会被解释成通配符,可以直接使用
- 但是不能进行浮点计算
11.7.3 浮点解决方案
使用bash内建的bc计算器:bc
基本用法:shell下使用bc命令行进入bash计算器
$ bc #进入bc计算器
$ bc -q #进入bc计算器,且不显示普通进入时展示的bc欢迎信息
1+2
3# 进入后shell输入后,shell输入符消失,可以进行运算输入输出
- 在bc内可以设置scale符号,指定输出结果的小数位数
- quit退出bc
脚本中使用bc - 基本格式:variable=$echo "options; expression" | bc)
variable=$echo "scale=4; 3.44/5" | bc)
echo $var1
./test
.6880
- 使用内联重定向
$ cat test12
#!/bin/bash
var1=10.46
var2=43.67
var3=33.2
var4=71
var5=$(bc << EOF
scale = 4
a1 = ( $var1 * $var2)
b1 = ($var3 * $var4)
$ #这一串输入的最终输出是a1 + b1
a1 + b1
EOF
)
echo The anwser is $var5
11.8 退出脚本
- 退出码:范围0 - 255。0表示正常执行退出。
11.8.1 查看退出状态码
- 运行中结束后,立刻运行 $? 命令可以返回退出码。
11.8.2 exit命令:指定退出码
- 脚本最后一行 exit 5/exit $var_name。
- 但是如果后面指定的常量值或变量的值大于255,那么将会返回整除255的余数。
第12章 使用结构化命令
12.1 使用If-then语句
if command
then commands
fi
- 只要command运行成功(状态为0),commands就会被执行。
12.2 if-then-else 语句
if command
then
commands
else
commands
fi
12.3嵌套if:elif
12.4 test命令
- if-then语句无法执行状态码之外的条件。
- if test variable
- if [ condition ]
12.4.1 数值比较
- -eq/ge/gt/le/lt/ne n2
等于,大于等于,大于,小于等于,小于,不等于 - 无法测试浮点数
12.4.2 字符串比较
- str1=/!=/</>/ str2
- 等于,不等于,小于,大于
- 大于小于号必须进行转义,否则会解释为重定向。
-
大于小于的顺序和sort命令的顺序是不同的。比较命令认为大小小于小写,而sort相反。因为比较使用
ASCII顺序,而sort使用本地的设置,本地设置的小写字母在大写字母前。
- -n/z str1
长度为非0,长度为0
12.4.3 文件比较
![0b22ac682d375b9f946b6691110d334a.png](en-resource://database/16725:0)
12.5 复合条件
- and:[ condition1 ] && [ condition2 ]
- or: [ condition1 ] || [ condition2 ]
12.6 if-then的高级特性
12.6.1使用双括号:数学表达式
((expression))
除了表中的高级表达式外,也可以使用上方的大于小于等基础比较符号,且不需要使用反转义符。
12.6.2 使用方括号:高级字符串表达式
[[expression]]
可以使用匹配模式
$ if [[ $USER == r* ]] # 如果用户名是r开头
12.7 case命令
case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) # 在上方列出的模式外的所有情况,执行默认指令
default commands;;
esac
- pattern是可以使用通配符的。
第13章 更多的结构化命令
13.1 for命令
基本格式
for var in list
do
commands
done
13.1.1读取列表中的值
for test in hunan hubei shanxi
- 使用空格分隔
- 如果需要使用单引号,或单个元素中间需要使用空格,可以使用双引号囊括
13.1.3 从变量读取列表
list="hunan hubei shanxi"
# 在已有字符串变量后新增字符串的方法
list=$list" henan"
for state in $list
do
echo "Have you ever visited $state"
done
13.1.4 从命令中读取值
file="states"
# cat获取文件states中的内容,再使用for进行遍历
for state in $(cat $file)
do
echo "Visiting $state
done
13.1.5 更改字符分隔符
- IFS Internal field separator,内部字段分隔符
- bash shell默认空格,制表符,换行符为IFS
- 修改IFS:IFS=$'\n
- 备份当前IFS并在之后恢复:IFS.OLD='\n';IFS=$IFS.OLD
- 指定多个字符为IFS: IFS='\n:;'#换行,分号,冒号为IFS
13.1.6 用通配符读取目录
for file in CHAP13/* #file遍历全部文件和文件夹
可以在一个for语句,连续遍历多个文件夹,以空格分隔即可
for file in CHAP13/* CHAP14/*
13.2 C语言风格的for命令
基本格式
for (( variable assignment ; condition ; iteration process))
# 并不需要使用美元符来引用变量
for (( a = 1 ; a < 10 ; a++))
do
echo "The next number is $i"
done
13.2.2 使用多个变量
# 同时迭代a和b
for (( a = 1, b = 10; a <= 10; a++, b-- ))
do
echo "$a - $b"
done
13.3 while命令
13.3.1 基本格式
while command
do
commands
done
13.3.2 使用多个测试命令
- while后进行多个测试命令。最后一个测试命令的退出状态码会决定是否退出循环。
var1 = 10
while echo $var1
# 每个测试命令为单独一行
[ $var1 -ge 0]
do
echo "loop is not ended"
var1=$[ $var1 - 1]
done
13.4 until命令
格式,多个命令测试与while一致;跳出循环的方式与while相反
13.5嵌套循环
(与其他语言一样) while, for, until都是可以互相嵌套的。
13.6 循环处理文件数据
使用两个for嵌套循环,每层分别指定不同的IFS,来遍历/etc/paswd的每行,每个冒号分隔符的内容。
13.7 控制循环
13.7.1 break命令
1.一层循环时,跳出循环
2.多层循环时,break:跳出最内层循环 break n 由内往外在停止n层的循环
13.7.2 continue循环
与break终止一层循环不同,continue只会提前终止某次循环(在这次循环中,不执行continue后的命令)
continue n 可以指定往外跳多少层,继续命令。
13.8 处理循环的输出
在done命令 加一个输出命令实现for循环内的所有输出到屏幕的内容输出到文件。
也可以像管道一样,将整个循环作为管道中的一节(一个命令)。
第14章 处理用户输入
$0 程序名
- 在程序启用语句后,以空格分隔参数 ./test3.sh param1 param2
- 如果单个参数内包含空格,以双引号包围该参数
9 第i个参数
参数序号大于9时的参数引用方式 ${10} - 如果不是在当前目录下直接调用脚本,那么$0将传递包含路径的脚本名。可以使用basename命令引用不包含路径的脚本名
$ name=${basename $0}
- 判断参数是否存在
$ if [ -n "$1" ]
$ ...
$fi
14.2特殊参数变量
- $# 返回参数的个数
- 花括号内不能使用美元符,而需使用感叹符或赋值给其他参数
$ #使用叹号引用
$ echo the last parameter was ${!#}
$ #使用参数赋值方法引用
$ params=$#
$ echo the last parameter was $params
14.2.2 获取所有参数
- $* 将所有参数作为一个整体引用。
- $@ 将所有参数作为多个独立的单词,可以使用for等方式进行遍历。
- 注意使用时需要在@ 加上双引号[why?]
14.3 移动变量
shift :所有参数往左移动一个位置,第一个被删除。理解成python的list pop(0)
- 常用于传了未知个数的参数,使用一个while [ -n "1这个变量,再shift,以此遍历全部参数。
- 可以加参数n来移动n个位置: shift n。
14.4 处理选项
第X章 零散
cron 周期性调度
crontab -l
- date +%Y%m%d 返回加号后指定样式的日期
日期加减计算-d
date -d"2 week ago 1 day ago" +"%Y%m%d"