1.初始Linux shell

  • Linux内核
    • 系统内存管理
    • 软件程序管理
    • 硬件设备管理:字符型、块、网络设备文件
    • 文件系统管理
  • GNU工具:coreutils软件包
  • 图形化桌面环境:X Window、KDE、GNOME、Unity
  • 应用软件

2.走进shell

  • 设置终端颜色
    • setterm -foreground blue
    • setterm -background yellow
    • 清除设置并清屏:setterm -reset
  • 控制台终端:退出图形化桌面模式,进入文本模式
  • 图形化终端:图形化界面里的Terminal

3.基本的bash shell命令

  • man
  • 链接:
    • 符号链接:ln -s 源文件 链接文件 (链接文件为新文件)
    • 硬链接:ln 源文件 链接文件(链接文件和源文件指向同一个文件)
  • mv 移动文件或重命名文件,文件的inode不变 。 ls -i
  • tree
  • file 文件类型

4.更多的bash shell命令

  • ps
  • top
  • kill killall
  • mount umount
  • df
  • du
  • sort -t ‘:’ -k 3 -n /etc/passwd
  • grep egrep fgrep
  • 压缩数据:gzip gzcat gunzip
  • 归档数据:tar
    • 创建归档文件:tar -cvf test.tar test1/ test2/
    • 查看归档文件:tar -tf test.tar
    • 提取归档文件:tar -xvf test.tar

5.理解shell

  • 进程列表:括号使命令列表变成了进程列表,生成一个子shell来执行对应的命令
# 命令列表
[root@localhost ~]# pwd;ls ;cd /etc;pwd;cd;pwd;ls;ps --forest;echo $BASH_SUBSHELL
/root
anaconda-ks.cfg
/etc
/root
anaconda-ks.cfg
    PID TTY          TIME CMD
   1833 pts/0    00:00:00 bash
   1990 pts/0    00:00:00  \_ ps
0

# 进程列表
[root@localhost ~]# (pwd;ls ;cd /etc;pwd;cd;pwd;ls;ps --forest;echo $BASH_SUBSHELL)
/root
anaconda-ks.cfg
/etc
/root
anaconda-ks.cfg
    PID TTY          TIME CMD
   1833 pts/0    00:00:00 bash
   1991 pts/0    00:00:00  \_ bash
   1994 pts/0    00:00:00      \_ ps
1

# BASH_SUBSHELL 是否创建子shell,可以嵌套括号创建子shell的子shell
[root@localhost ~]# (pwd;echo $BASH_SUBSHELL)
/root
1
[root@localhost ~]# (pwd;(echo $BASH_SUBSHELL))
/root
2
  • 将进程置入后台
    • ‘&’
    • 查看后台进程:jobs -l
    • 协程:
      • coproc sleep 10
      • coproc My_Job {sleep 10}
  • 内建命令和外部命令的区别在于前者不需要使用子进程来执行。它们已经和shell编译成一体,作为shell工具的组成部分存在。
[root@localhost ~]# type ps
ps is hashed (/usr/bin/ps)
[root@localhost ~]# type cd
cd is a shell builtin
[root@localhost ~]# type -a pwd
pwd is a shell builtin
pwd is /usr/bin/pwd
  • history
    • a 强制写入history文件(.bash_history)
    • n 同步,当存在多个客户端时
    • c 清除
  • !! 执行上一条命令;!20 执行第20条命令
  • alias 别名
    • p 查看当前可用别名
    • 创建别名 alias lxq=‘ls -la’

6.什么是环境变量

  • 全局环境变量对于shell绘画和所有生成的子shell都是可见的。局部变量则值对创建它们的shell可见。
  • printenv和env 显示全局变量,set显示全局变量、局部变量和用户自定义变量
  • 设置用户自定义变量,变量名、等号和值之间不能有空格。my_variable=“Hello World”
  • 设置全局变量:先创建局部环境变量,然后再把它导出到全局环境中。export my_variable
    • 修改子shell中全局变量并不会影响到父shell中该变量的值。
  • 删除环境变量:unset my_variable
    • 在子shell中删除全局变量,并不会影响父shell全局变量
  • 常用的环境变量
    • UID、EUID
    • PPID:父进程ID
    • RANDOM:0~32767的随机数
    • BASH_ARGC、BASH_ARGV
    • FUNCNAME:当前执行的函数名称
    • HOSTNAME
  • 设置环境变量:PATH,定义了用于执行命令和程序查找的目录。PATH=$PATH:/home/work/bin
  • 启动bash shell的三种方式
    • 登录时作为默认登录shell。会从5个不同的启动文件里读取命令
      • /etc/profile。此脚本会加载/etc/profile.d文件夹下的脚本
      • 用户专属启动文件,shell会按如下顺序查找如下三个文件,找到第一个余下的被忽略
        • $HOME/.bash_profile
        • $HOME/.bash_login
        • $HOME/.profile
      • $HOME/.bashrc
    • 作为非登录shell的交互式shell:(例如在命令行下敲入 bash),它不会访问/etc/profile,只会检查用户HOME目录中的.bashrc文件
    • 作为运行脚本的非交互shell:系统执行shell脚本。当shell启动一个非交互shell时,它会检查BAHS_ENV环境变量查看执行的启动文件,如果没有BASH_ENV,那么作为子shell的,子shell继承父shell的导出的变量,不启动子shell的,局部变量和全局变量已存在与当前shell中
  • 环境变量持久化
    • 对于全局变量,可在/etc/profile中添加,但是此文件会随着发行版升级版本变化,最好是在/etc/profile.d目录中创建一个.sh结尾的文件。把所有新的和修改过的全局变量设置在这个文件中
    • 存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件
  • 数组变量:要给某个环境变量设置多个值,可以把值放在括号里,用空格分割。数组变量可移植性不好,在其他shell中可能存在问题,慎重使用
mytest=(one  two  three four five)
echo $mytest # one
echo ${mytest[1]} # two
echo ${mytest[*]} # one two three four five
mytest[2]=lxq
unset mytest[2] # 删除第二个元素的值,此时mytest[2]为空值

7.Linux的安全性

  • useradd work [-G groupname]
  • userdel -r work # r删除work的HOME目录以及邮件目录
  • usermod:修改用户账户
    • L锁定账户,无法登录
    • U解锁账户
    • G 添加组:usermod -G groupname username
  • passwd、chpasswd 批量修改用户名密码
  • chsh:修改默认用户登录sh,chsh -s /bin/csh test
  • chfn:修改账户备注信息,grep work /etc/passwd可查看修改结果
  • chage用来帮助管理用户账户有效期
  • groupadd [groupname]
  • groupmod -n working work # 修改组名
  • umask:默认文件权限。对于文件,全权限值为666,对于目录全权限值为777
touch test.txt
mkdir test.d
drwxr-xr-x. 2 root root        6 Jan 23 19:29 test.d
-rw-r--r--. 1 root root        0 Jan 23 19:29 test.txt
  • chmod:权限修改。 R 递归作用
  • chown:属主修改。 R 递归作用
    • 修改用户:chmod work test.txt
    • 修改用户和组:chmod work.work test.txt
    • 修改用户和组:chmod work. test.txt
    • 修改组:chmod .work test.txt
  • chgrp:修改数组
  • 共享文件。SGID位对于文件共享非常重要。启用SGID位后,可以强制在一个共享目录下创建新文件都属于该目录的属组,这个组就成为了每个用户的属组。
    • SUID(4):当文件被用户使用时,程序会以未见属主的权限运行。chmod u+s file
    • SGID(2):对文件来说,程序会以文件数组的权限运行;对于目录来说,目录中创建的新文件会以目录的默认属组作为默认属组。chmod g+s file
    • 粘着位(1):进程结束后文件还驻留(粘着)在内存中。chmod o+t file

8.管理文件系统

  • 日志文件系统:ext4、XFS
  • 写时复制文件系统:ZFS、Btrf,如果修改数据,会使用克隆或可写快照
  • 创建分区 fdisk
    • fdisk -l 列出分区信息
    • fdisk /dev/sdb 操作分区
  • 挂载 mount -t ext4 /dev/sdb1 /mnt/my_partition
  • 文件系统检查:fsck

逻辑卷管理

  • 物理卷(physical volume,PV):每个物理卷都会映射到硬盘上特定的物理分区
  • 卷组(volume group,VG):多个物理卷集中在一起可以形成一个卷组。逻辑卷管理系统将卷组视为一个物理硬盘,但事实上卷组可能是由分区在多个物理硬盘上的多个物理分区组成的。卷组提供了一个创建逻辑分区的平台,而这些逻辑分区则包含了文件系统。
  • 逻辑卷(logical volume,LV):为Linux提供创建文件系统的分区环境
  • 快照snapshot:
  • 镜像:实时更新的逻辑卷的完整副本,当创建镜像逻辑卷时,LVM会将原始逻辑卷同步到镜像副本中
  • 条带化:跨多个硬盘创建逻辑卷,文件数据块分散到多个硬盘,增加性能
  • 使用LVM
# 分配两个8G的硬盘,/dev/sdc /dev/sdb,使用下面命令查看是否成功
fdisk -l

# 对/dev/sdc /dev/sdb分别进行分区,重复操作建立三个分区
fdisk /dev/sdc
Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p):

Using default response p.
Partition number (1-4, default 1):
First sector (2048-16777215, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-16777215, default 16777215): +2G

Created a new partition 1 of type 'Linux' and of size 2 GiB.

Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): 8e
Changed type of partition 'Linux' to 'Linux LVM'.

Command (m for help): p
Disk /dev/sdc: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xe54e9c4c

Device     Boot Start     End Sectors Size Id Type
/dev/sdc1        2048 4196351 4194304   2G 8e Linux LVM

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

# 用分区创建物理卷
pvcreate /dev/sdc1 /dev/sdc2 /dev/sdc3 /dev/sdb1 /dev/sdb2 /dev/sdb3
# 查看物理卷
pvdisplay
# 创建卷组,选中四个物理卷
vgcreate vg_lxq /dev/sdc1  /dev/sdc3 /dev/sdb1 /dev/sdb3
# 查看卷组
vgdisplay vg_lxq
# 创建逻辑卷 L 指定大小 n 指定逻辑卷名称
lvcreate -L 3G -n lv_sda1 vg_lxq
# 查看逻辑卷详细情况
lvdisplay vg_lxq
# 创建文件系统和挂载
mkfs.ext4 /dev/vg_lxq/lv_sda1
mount  /dev/vg_lxq/lv_sda1 /mnt/my_partition
mount # /dev/mapper/vg_lxq-lv_sda1 on /mnt/my_partition type ext4 (rw,relatime,seclabel)
# ext4扩容
lvresize -L 4G /dev/vg_lxq/lv_sda1
e2fsck -f /dev/vg_lxq/lv_sda1
resize2fs /dev/vg_lxq/lv_sda1 # ext4信息就更新
# ext4缩减
umount /dev/vg_lxq/lv_sda1
e2fsck -f /dev/vg_lxq/lv_sda1
resize2fs /dev/vg_lxq/lv_sda1 3G
lvresize -L 3G /dev/vg_lxq/lv_sda1 

# xfs扩容
lvcreate -L 1G -n lv_sda2 vg_lxq
mkfs.xfs /dev/vg_lxq/lv_sda2
mkdir /mnt/my_xfs
mount /dev/vg_lxq/lv_sda2 /mnt/my_xfs
lvresize -L 2G /dev/vg_lxq/lv_sda2
xfs_growfs /dev/vg_lxq/lv_sda2
umount /dev/vg_lxq/lv_sda2
dd if=/dev/zero bs=1M count=1000 of=/mnt/my_xfs/test1000M.zero

# 删除物理卷
vgreduce vg_lxq /dev/sdc1
# 扩展卷组
vgextend vg_lxq /dev/sdc2

# 创建快照 -s创建快照 -L快照大小 -n快照名称
lvcreate -s -L 500M -n lvsda1snap2 /dev/vg_lxq/lv_sda1
# 查看快照
lvdisplay /dev/vg_lxq/lvsda1snap2

# pvs vgs lvs  

9.安装软件程序

  • centos yum
# 
yum list
yum list nginx
yum list installed 
yum list installed nginx

# 查找/etc/yum.conf属于那个软件包
yum provides /etc/yum.conf

yum install nginx
# yum本地安装rpm安装文件
yum localinstall package_name.rpm

# 列出现有已安装包的可用更新
yum list updates

yum update package_name
# 更新所有更新
yum update
# 只删除软件包而保留配置文件和数据文件
yum remove package_name
# 删除软件和它的所有文件
yum erase package_name

yum clean all

# 显示包的依赖关系
yum deplist package_name

11.构建基本脚本

  • echo -n 无换行符
  • 命令替换
    • date
    • $(date)
  • 管道(|),不要以为管道串起的两个命令会依次执行。Linux系统实际上会同时运行这两个命令,在系统内部将它们连接起来,在第一个命令产生输出的同时,输出会立即送往第二个命令。数据传输不会用到任何中间文件或缓冲区。
  • 执行数学运算,bash shell 只支持整数运算,浮点运算可考虑使用zsh、bc计算器
var1=$(expr 2 \* 5)
var2=$[2*5]
  • 使用bc计算浮点数
var1=$(echo "3+4"|bc)
# EOF内联输入重定向
var5=$(bc << EOF
scale=4
a1 = ($var1 * $var2)
a2 = ($var3 * $var4)
a1+a2
EOF) 
  • 退出 $?可查看退出码,exit可指定退出码

12.使用结构化命令

  • if-then:if后面的命令的退出状态码为0(该命令成功执行),位于then部分的命令就会被执行。
if pwd
then
  echo "It worked"
else
  echo "It don't worked"
fi

if pwd;then
  xxx
elif ls -d /home/work ; then
  xxx
else 
  xxx
fi 
  • test:提供了在if-then语句中测试不同条件的路径。如果test命令列出的条件成立,test命令就会退出并返回退出状态码0;不成立则返回非零退出状态码。test可处理下列三种条件
    • 数值比较,-eq -ge -gt -le -lt -ne
    • 字符串比较,= != < >
      • < > 必须采用转义
      • -n str1 检查str1的长度是否为非0
      • -z str1 检查str1的长度是否为0
    • 文件比较
      • -d file 检查file是否存在并且是一个目录
      • -f file 检查file是否存在并且是一个文件
      • -e file 检查file是否存在
      • -[r|w|x] file 检查file是否可读、可写、可执行
      • -s file 检查file是否存在并非空
      • -O file 检查file是否存在并属于当前用户所有
      • -G file 检查file是否存在并且默认组与当前用户相同
      • file1 -nt file2 检查file1是否比file2新
      • file1 -ot file2 检查file1是否比file2旧
  • test命令可用中括号代替,在第一个方括号之后和第二个方括号之前必须加上一个空格,否则会报错。if [ condition ];then fi
  • 复合条件测试 [ cond1 ] && [ cond2 ];[ cond1 ] || [ cond2 ];
  • 使用双括号命令允许正在比较过程中使用高级数学表达式
if (( 3 ** 4 == 81 ));then
        echo "3**4==81"
fi
  • 使用双方括号可以进行字符串模式匹配
if [[ $USER == r* ]];then
        echo "user r*"
fi
  • case语句,|可以匹配多个值,;;为每一个case结束,*)捕获所有和已知模式不匹配的值。
case $USER in
rich | junmo)
  echo "xxx"
  echo "hello";;
testing)
  echo "testing";;
*)
  echo "default";;
esac

13.更多的结构化命令

  • 内部字段分隔符IFS,bash shell默认把空格、制表符、换行符当做字段分隔符。
IFS=:
IFS=$'\n':;"

IFS.OLD=$IFS
IFS=$'\n'
#在代码中使用新的IFS值
IFS=$IFS.OLD
  • for
# 从列表读取
for test in I don\'t know if "this'll" work
do
  echo $test
done

# 从变量读取
list="AB C D E"
list=$list" F"
for state in $list
do
  echo $state
done
  
# 从命令读取
for f in $(cat $file)
do
  echo $f
done

# 读取目录,可以读取多个
for file in /etc/* /home/work
do
  if [ -d "$file" ]
  then
    echo "$file is a directory"
  elif [ -f "$file" ]
  then
    echo "$file is a file"
  fi
done
  • C语言风格for循环
for (( i = 0;i<10;i++))
do
  echo "index $i"
done
  • while:使用多个测试命令时,每个测试命令为一行,只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环
var1=10
while echo $var1
      [ $var1 -ge 0 ]
do 
  echo "This is inside the loop"
  var1=$[ $var1 - 1 ]
done
  • until命令:和while相反,当命令执行退出状态码返回零时退出
  • 嵌套循环nested loop
  • 循环处理文件数据
    • 使用嵌套循环
    • 使用IFS环境变量
IFS.OLD=$IFS
IFS=$'\n'
for entry in $(cat /etc/passwd)
do
  echo "Value in $entry -"
  IFS=:
  for value in $entry
  do
    echo " $value"
  done
done
IFS=$IFS.OLD
  • 控制语句break continue,其中break n为打断第n层外部循环
  • 循环输出,可以在done之后重定向到文件,也可以使用管道符,如 done>test123.txt; done | sort

14.处理用户输入

  • 命令行参数 1 , 1, 1,{10}
  • 读取脚本名 0 , 0, 0,(basename $0)
  • [ -n “$1” ] 测试参数是否存在
  • 参数个数: $# 最后一个变量: ${!#}
  • 抓取所有数据,$* 和 @ , @ , @* 变量会将所有参数当成单个参数,而 $@ 变量会单独处理每个参数
  • shift移动变量,可以用来跳过不需要的变量
# test.sh 1 2 3 4 5
echo "first parm: $1" # 1
shift 2
echo "first parm: $1" # 2
  • 处理选项getopt:将命令行选项和参数处理只生成一个输出。命令行执行:
$ getopt ab:cd -a -btest1 -cd test1 test2
 -a -b test1 -c -d -- test1 test2
  • 处理选项getopts:shell内置命令,每次调用只检测一个参数,$OPTARG为当前解析的值,OPTIND为当前处理的位置加1
while getopts :ab:c opt
do
  case "$opt" in
    a) echo "Found the -a option" ;;
    b) echo "Found the -b option, with value $OPTARG" ;;
    c) echo "Found the -c option" ;;
    *) echo "Unknown option: $opt"
  esac 
done

# 处理参数
shift $[ $OPTIND -1 ]
count=1
for param in "$@"
do
  echo "Parameter $count: $param"
  count=$[ $count + 1 ]
done

$ bash a.sh -a -btest1 -c --  testaaa sjsjjs
Found the -a option
Found the -b option, with value test1 
Found the -c option
Parameter 1: testaaa
Parameter 2: sjsjjs
  • 获取用户输入:read,如果没有指定变量,则在全局变量REPLY中
read -p "Enter your name: " name
read name
# 等待5s
read -t 5 name
# n指定当输入的字符达到指定字数时,自动退出
read -n 1 name
# 隐藏方式读取
read -s pass
# 从文件读取,每次读取一行
count=1
cat test.txt | while read line
do
  echo "Line $count: $line"
  count=$[ $count+1 ]
done

15.呈现数据

  • STDIN 0 ;STDOUT 1 ;STDERR 2;
  • 重定向错误 2>
  • 重定向错误和数据 &>
  • 临时重定向:在重定向到文件描述符时,必须在文件描述符数字之前加一个 &
echo "this is an error" >&2
  • 永久重定向:在脚本中使用exec告诉脚本执行期间重定向某个特定文件描述符
exec 1> testout
exec 2> testerror
  • 重定向输入
#!/bin/bash
exec 0< a.sh
count=1
while read line
do
        echo "Line #$count: $line"
        count=$[ $count+1 ]
done
  • shell脚本中最多可以有9个文件描述符
# 创建输出文件描述符
exec 3> test13out

echo "test13out hhh" >&3
  • 重定向文件描述符,恢复
# 重定向3到STDOUT
exec 3>&1
# 重定向STDOUT到文件
exec 1> testout
# 3指向STDOUT,所以1重定向到3,则还原重定向
exec 1>&3
  • 创建读写文件描述符 exec 3<> testfile
  • 关闭文件描述符 exec 3>&-
  • 列出打开的文件描述符:lsof
  • 组织命令输出 2> /dev/null
  • 创建临时文件 mktemp
# 在本地创建临时文件 X会被系统填充随机字符串
mktemp testing.XXXXX
# 在临时目录创建临时文件 t
mktemp -t testing.XXXXX
# 在临时目录创建临时目录 d
mktemp -d dir.XXXXX
  • tee file:将STDIN的数据发往STDOUT和文件file,追加数据到文件使用 -a 选项

16.控制脚本

  • SIGINT:CTRL+C会生成此信号
  • SIGTSTP:Ctrl+Z
  • 捕获信号:trap commands signals
    • 捕获信号:trap “echo ’ Sorry… Ctrl+C is trapped.’” SIGINT
    • 捕获脚本退出:trap “echo Goodbye…” EXIT
    • 修改捕获:trap “echo ’ I modified the trapped.’” SIGINT
    • 移除捕获:trap – SIGINT
#!/bin/bash
trap "echo Goodbye..." EXIT
trap "echo ' Sorry... Ctrl+C is trapped.'" SIGINT
count=1
while [ $count -le 5 ]; do
  echo "Loop1: #$count"
  sleep 1
  count=$[ $count+1 ]
done
trap "echo ' I modified the trapped.'" SIGINT
count=1
while [ $count -le 5 ]; do
  echo "Loop2: #$count"
  sleep 1
  count=$[ $count+1 ]
done
trap -- SIGINT
count=1
while [ $count -le 5 ]; do
  echo "Loop2: #$count"
  sleep 1
  count=$[ $count+1 ]
done
  • 后台运行脚本:&,但是要注意在终端会话退出时,后台进程也会随之退出,因为终端退出时,会给它的子进程发送SIGHUB信号
  • nohup命令会解除终端和进程的关联
  • 作业控制jobs
    • l 列出进程PID及作业号
    • n 只列出上次shell发出通知后改变状态的作业
    • p 只列出PID
    • r 只列出运行中的作业
    • s 只列出已停止的作业
  • 重启停止作业
    • bg [n] 后台启动
    • fg [n] 前台启动
  • 调整谦让度
    • nice -n 10 ./test.sh &
    • renice -n 15 -p 22233
  • 定时任务
    • 一次性执行 at
    • 周期性执行 cron
    • ancron:处理由于关机错过的脚本任务

17.创建函数

  • 函数 function name {}
  • 返回值:
    • 使用return返回状态码,范围为0~255,必须函数结束就获取
    • 使用函数输出
function foo {
    read -p "Enter a value: " value
    echo "doubling the value"
    return $[ $value * 2 ]
}
foo
echo "The new value is $?"

function bar {
    read -p "Enter a value: " value
    echo $[ $value * 2 ]
}
result=$(bar)
echo "The new value is $result"
  • 函数传递参数 foo param1 param2 …,获取参数为 $1 $2 …,
  • 全局变量:默认情况下,在脚本中定义的任何变量都是全局变量,在函数内可正常访问
#!/bin/bash

function ttt {
    aaa=$[ $aaa*2 ]
}
aaa=10
ttt
echo "aaa: $aaa" # aaa: 20
$(ttt) # 子shell执行,不会修改aaa的值
echo "aaa: $aaa" # aaa: 20
  • 局部变量:local
function ttt {
    local aaa=$[ $aaa*2 ]
}
aaa=10
ttt
echo "aaa: $aaa" # aaa: 10
  • 函数数组输入输出
#!/bin/bash
function ttt {
   local aaa=($(echo "$@"))
   echo "new array: ${aaa[*]} count:$#"
}

function ttt2 {
   local aaa=($(echo "$@"))
   local reaaa
   for (( i=0;i<$#;i++))
   {
       reaaa[$i]=$[ ${aaa[$i]} * 2 ]
   }
   echo ${reaaa[*]}
}
aaa=(10 20 30 40 50)
echo "original arr: ${aaa[*]}"
ttt ${aaa[*]}
arg=$(ttt2 ${aaa[*]})
echo $arg # 20 40 60 80 100
arg=($(ttt2 ${aaa[*]}))
echo $arg # 20
echo ${arg[*]} # 20 40 60 80 100
  • 递归
# 阶乘
function factorial {
    if [ $1 -eq 1 ]
    then
        echo 1
    else
        local temp=$[ $1 - 1 ]
        local result=$(factorial $temp)
        echo $[ $result * $1 ]
    fi
}
  • 创建库,使用库函数的关键在于source命令。source会在当前shell上下文中执行命令,而不是新建一个shell。可以用source在shell脚本中运行库文件脚本,source有个快捷命名,称为点操作符
#!/bin/bash
. ./my_func.sh
  • 命令行使用函数
    • 可在命令行直接创建函数
    • 在.bashrc里创建函数,也可以在.bashrc里引入函数库

18.图形化桌面环境的脚本编程

  • select
#!/bin/bash
function diskspace {
    clear
    df -k
}
function whoseon {
    clear
    who
}
function memusage {
    clear
    cat /proc/meminfo
}
function memu {
    clear
    echo
    echo -e "\t\t\tSys Admin Memu\n"
    echo -e "\t1. Display disk space"
    echo -e "\t2. Display logged on users"
    echo -e "\t3. Display memory usage"
    echo -e "\t0. Exit program\n\n"
    echo -en "\t\tEnter option: "
    read -n 1 option
}
# while [ 1 ]
# do
#     memu
#     case $option in
#         0) break ;;
#         1) diskspace ;;
#         2) whoseon ;;
#         3) memusage ;;
#         *)
#             clear
#         echo "Sorry, wrong selection" ;;
#     esac
#     echo -en "\n\n\t\tHit any key to continue."
#     read -n1 line
# done
# clear

PS3="Enter option: "
select option in "Display disk space" "Display logged on users" "Display memory usage" "Exit program"
do
    case $option in
        "Exit program") break ;;
        "Display disk space") diskspace ;;
        "Display logged on users") whoseon ;;
        "Display memory usage") memusage ;;
        *)
            clear
        echo "Sorry, wrong selection" ;;
    esac
    echo -en "\n\n\t\tHit any key to continue."
    read -n1 line
done
  • dialog:每个dialog提供两种输出,可以通过退出状态码来确定用户选择了那个按钮,如果选择了Yes或OK按钮,返回状态码为0;如果选择了Cancel或No按钮则退出状态码为1。如果部件返回了数据,那么命令会将数据发送到STDERR
    • msgbox:对话框显示一条消息,直到用户点击ok才消失。dialog --msgbox text height width
      • dialog --title “lxq” --msgbox “this is a msg” 10 20
    • yesno部件:扩展了msgbox部件,有两个按钮
      • dialog --title “lxq” --yesno “this is a msg” 10 20
    • inputbox:提供了一个简单的文本框区域来输入文本字符串
      • dialog --title “inputbox lxq” --inputbox “Enter your age” 10 20 2>age.txt
    • textbox:在窗口中显示大量信息的方法,如下展示/etc/passwd文件的内容
      • dialog --textbox /etc/passwd 10 20
    • menu部件:dialog --menu title height width 每页数量
      • dialog --menu “Sys Admin Menu” 20 30 10 1 “Display disk space” 2 “Display logged on users” 3 “Display memory usage” 4 “Exit program” 2> test.txt
    • fselect: 处理文件夹
      • dialog --title “Select a file” --fselect $HOME/ 10 20 2>file.txt
  • 图形化X Window环境下
    • KDE桌面:kdialog
    • GNOME桌面:gdialog和zenity

19-22 sed awk使用

  • sed awk使用

更多推荐

Linux命令行与shell脚本编程大全v3 Richard Blum