0%

shell笔记-1

参考自Linux命令行与shell脚本编程大全第三版

  1. 输出特殊字符

比如需要输出换行符时
使用echo $'\n'
双引号是没用的, 只会输出普通字符串

  1. UNIX哲学

参考https://yuguo.us/weblog/linux-philosophy/

  1. shell哲学

参考https://www.cnblogs.com/youxia/p/linux010.html

  1. continue

来自man
复位到外层for, while, until, 或select循环的下一次开始. 如果指定了n, 复位到向外第n层循环的开始. n必须>=1. 如果n比外部循环的层数要多, 将复位到最外层的循环(top-level loop, 顶层循环). 返回值是0, 除非执行continue时, shell不是在循环之中.

  1. 命令和语法总结
  • man -k terminal
    查找与关键字相关的命令
  • man 1 hostname
    显示该命令的手册的第几部分
  • 文件扩展匹配
    使用(元字符)通配符进行过滤, 如* ? [] !
  • file my_file
    查看文件类型
  • tail -f my_log
    可用于实时监测系统日志
  • (pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls)
    进程列表, 会生成子shell
  • { pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls } 或 pwd ; ls ; cd /etc ; pwd ; cd ; pwd ; ls
    不会生成子shell, 注意{ }前后有空格
  • coproc sleep 10 或 coproc my_job { sleep 10; }
    协程, 在后台生成一个子shell, 并在这个子shell中执行命令
  • type -a echo
    显示每个命令的两种实现(内建命令和外部命令)
  • which pwd
    只显示外部命令文件
    外部命令, 也被称为文件系统命令, 是存在于bash shell之外的程序, 并不是shell程序的一部分
    通常位于/bin, /usr/bin, /sbin或/usr/sbin中
    执行外部命令时, 会创建出一个子进程(forking)
  • !!
    执行刚刚执行过的命令
  • !20
    执行指定编号的命令
  • env 或 printenv
    查看全局变量
  • printenv HOME 或 echo $HOME
    查看指定的全局变量
  • set
    查看为某个特定进程设置的所有环境变量
    局部变量, 全局变量, 用户定义变量
  • my_var=hello 或 my_var=’hello world’ 或 my_var=”hello world”
    定义用户变量, 变量名用小写字母
  • export my_var
    导出局部变量
  • unset my_var
    删除环境变量
    注意, 在子shell中对全局变量的任何操作都无法影响父shell中的全局变量
  • my_arr=(one two three four five)
    数组
  • echo ${my_arr[2]}
    输出单个元素
  • echo ${my_arr[*]}
    输出整个数组
  • my_arr[2]=seven
    改变某个位置的值
  • unset my_arr[2]
    删除数组中的某个值, 但那个地方只会变成空, 其他地方的值不会变
  • unset my_arr
    删除整个数组
  • chpasswd < users.txt
    为系统中的大量用户修改密码, 格式 userid:passwd
  • chsh -s /bin/csh test
    修改默认的用户登录shell
  • chfn test
    在/etc/passwd文件的备注字段中存储信息
  • chage test
    管理用户账户的有效期
  • groupadd shared
    创建新组
  • usermod -G shared test
    添加用户到组
  • groupmod -n sharing shared
    修改组名, -g 选项可以修改GID
  • fdisk /dev/sdb
    管理磁盘分区
  • mkfs.ext4 /dev/sdb1
    创建文件系统, 不同的文件系统的创建有不同的命令
  • mount -t ext4 /dev/sdb1 /mnt/my_partition
    挂载文件系统, -t 选项指定了文件系统
  • fsck -a /dev/sdb1 或 fsck -y /dev/sdb1
    自动修复文件系统, 文件系统可以通过设备名, 在虚拟目录中的挂载点以及分配给文件系统的唯一UUID来引用
  • fdisk通过t命令定义分区类型8e
    分区类型8e代表这个分区将会被用作Linux LVM系统的一部分
  • pvcreate /dev/sdb1
    简单地将分区标记成Linux LVM系统中的分区, 即创建实际的物理卷
  • pvdisplay /dev/sdb1
    显示已创建的物理卷列表, 可查看创建进度
  • vgcreate voll /dev/sdb1
    创建卷组, 同时指定卷组名
  • vgdisplay voll
    查看新创建的卷组的细节
  • lvcreate -l 100%FREE -n lvtest voll
    创建逻辑卷
  • lvdisplay voll
    查看创建的逻辑卷的详细情况
  • mkfs.ext4 /dev/voll/lvtest
    创建文件系统
  • mount /dev/voll/lvtest /mnt/my_partition
    挂载文件系统
  • vgchange
    激活和禁用卷组
  • vgremove
    删除卷组
  • vgextend
    将物理卷加入到卷组中
  • vgreduce
    从卷组中删除物理卷
  • lvextend
    增加逻辑卷的大小
  • lvreduce
    减小逻辑卷的大小
  • ./configure
    检查Linux系统, 确保有适合的编译器能够编译源代码, 另外还要具备正确的库依赖关系
  • make
    构建各种二进制文件
  • make install
    将软件安装到Linux系统上常用的位置上
  • readlink -f /usr/bin/vi
    找出链接文件的最后一环
  • testing=$(date) 或 testing=`date`
    命令替换, 会创建一个子shell来运行对应的命令, 由该子shell所执行的命令无法使用脚本中所创建的变量
1
2
3
4
5
wc << EOF
test string 1
test string 2
test string 3
EOF

内联输入重定向符

  • expr 5 \* 2
    expr执行数学运算, 有些特殊的符号需要转义
  • var=$[5*2]
    方括号执行数学运算, bash shell只支持整数运算
  • var=$(echo “scale=4; 3.44 / 5” | bc) 或
1
2
3
4
5
6
7
var=$(bc << EOF
scale = 4
a1 = $var1 * $var2
b1 = $var3 * $var4
a1 + b1
EOF
)

实现对浮点数的计算

  • echo $?
    输出上一个已执行命令的退出状态码
  • exit 5
    退出的同时返回退出状态码
1
2
3
4
5
6
7
8
9
if command1
then
command set 1
elif command2
then
command set 2
else
command set 3
fi

if-then, elif-then, else, fi
elif-then和else都是可选的
if或elif后面的command退出状态码是0(成功运行), then后面的command set才会执行

  • test condition 或 [ condition ]
    测试条件表达式, 用在判断关键字后面, 注意[ ]前后有空格
    数值比较使用-eq -ge -gt -le -lt -ne
    字符串比较使用= != < > -n -z, <>必须转义
    test命令中使用标准的ASCII顺序, 根据每个字符的ASCII数值来决定排序结果; sort命令使用系统本地化语言设置中定义的排序顺序, 对于英语, 本地化设置指定了在排序顺序中小写字母出现在大写字母前
    文件比较使用-d -e -f -r -s -w -x -O -G -nt -ot
    复合条件测试使用&&||
  • ((expression)) 或 ((val2=$val1**2))
    允许在比较过程中使用高级数学表达式, test命令只能在比较中使用简单的算术操作, 双括号命令提供了更多的数学符号
    其他运算符: val++ val-- ++val --val ! ~ ** << >> & | && ||
    可以在脚本中的普通命令里使用来赋值
  • [[ $USER == r* ]]
    双方括号和test命令差不多, 但提供了模式匹配的特性
    不是所有的shell都支持双方括号, bash shell支持
1
2
3
4
5
6
7
8
9
10
11
case $USER in
rich | barbara)
echo "Welcome, $USER"
echo "Please enjoy your visit";;
testing)
echo "Special testing account";;
jessica)
echo "Do not forget to log off when you're done";;
*)
echo "Sorry, you are not allowed here";;
esac

case命令

1
2
3
4
5
6
7
8
9
10
for file in /home/rich/test/*
do
if [ -d "$file" ]
then
echo "$file is a directory"
elif [ -f "$file" ]
then
echo "$file is a file"
fi
done

for-in结构
可以用通配符读取目录, 强制shell使用文件扩展匹配
防止目录名和文件名中包含空格, 将$file变量用双引号圈起来

  • IFS=$’\n’:;”
    内部字段分隔符, 最好先将原来的IFS的值记录
1
2
3
4
for ((a=1,b=10;a<=10;a++,b--))
do
echo "$a - $b"
done

C语言风格的for结构

1
2
3
4
5
6
7
8
var1=10

while echo $var1
[ $var1 -ge 0 ]
do
echo "This is inside the loop"
var1=$[ $var1 - 1 ]
done

while结构, 可以使用多个测试命令, 但只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环

1
2
3
4
5
6
7
8
var1=100

until echo $var1
[ $var1 -eq 0 ]
do
echo Inside the loop: $var1
var1=$[ $var1 - 25 ]
done

until结构, 直到最后一个命令成立时停止

  • break 2
    跳出循环, 可以指定跳出的层数, 默认为1
  • continue 2
    复位到下一次循环, 可以指定回到第几层, 默认为1
1
2
echo $2
echo ${10}

命令行参数

1
name=$(basename $0)

获取不包含路径的脚本名

  • echo $#
    命令行参数个数
1
echo ${!#}

最后一个命令行参数变量

1
2
3
4
for param in "$*"
do
commands
done

$*会将所有参数当成单个参数

1
2
3
4
for param in "$@"
do
commands
done

$@会单独处理每个参数

  • shift 2
    向左移动命令行参数, 可以指定移动的位置数, 默认为1, 移动过程中$0不会变
Thank you for your reward !