Linux系统编程20-shell脚本入门
shell 是一个作为用户与Linux系统间接口的程序, 默认的shell程序 /bin/sh实际上是对程序 /bin/bash的一个连接
管道与重定向
重定向
重定向输出:
ls -l / > lsoutput.txt
使用>>附加输出内容:
ps >> lsoutput.txt
标准错误:
test.c 2> err.log
回收站丢弃输出信息:
kill -1 1234 >/dev/null 2>&1
重定向输入:
more < lsoutput.txt
管道
使用重定向对 ps 命令输出排序:
ps aux > psout.txt
sort psout.txt > pssort.out
使用管道对 ps 命令输出排序:
ps aux | sort > pssort.out
ps aux | sort | more
ps -xo comm | sort | uniq | grep -v sh | more
查看系统运行所有进程名
shell程序语言
通配符:
*
: 字符串?
: 单个字符[set]
: 方括号中任何一个单字符{}
: 任意字符串放到一个集合中
变量
- 所有变量都被看作字符串来存储, 使用
echo $x
打印 - 使用read命令将输入赋值给一个变量
- 环境变量:
$HOME
家目录$PATH
搜索命令$PS1
命令提示符$PS2
二级提示符$IFS
输入域分隔符$0
脚本名$#
传递给脚本参数个数$1,$2,..
脚本程序参数$*
一个变量中列出所有参数$@
$*
的变体, 不收IFS影响, 更好的选择$$
脚本进程号
#!/bin/sh
salutation="Hello"
echo $salutation
echo "The program $0 is now running"
echo "The second parameter was $2"
echo "The first parameter was $1"
echo "The parameter list was $*"
echo "The user's home directory is $HOME"
echo "Please enter a new greeting"
read salutation
echo $salutation
echo "The script is now complete"
exit 0
$ ./3_try_var foo bar baz
Hello
The program ./3_try_var is now running
The second parameter was bar
The first parameter was foo
The parameter list was foo bar baz
The user's home directory is /home/codespace
Please enter a new greeting
world!
world!
The script is now complete
条件循环
test -f <filename>
: 是一个普通文件为真
[ -d <filename> ]
: 是一个目录为真(有空格0)
#!/bin/sh
if [ -f /bin/bash ]
then
echo "file /bin/bash exists"
fi
if [ -d /bin/bash ]
then
echo "/bin/bash is a directory"
else
echo "/bin/bash is NOT a directory"
fi
使用if语句
#!/bin/sh
echo "Is it morning? please answer yes or no?"
read timeofday
if [ $timeofday = "yes" ]; then
echo "Good morning"
elif [ $timeofday = "no" ]; then
echo "Good afternoon"
else
echo "sorry, $timeofday not recognized. Enter yes or no"
exit 1
fi
exit 0
Is it morning? please answer yes or no?
yes
Good morning
for语句
#!/bin/sh
for file in $(ls f*.sh); do
lpr $file
done
exit 0
while语句
#!/bin/sh
echo "Enter password"
read trythis
while [ "$trythis" != "secret" ]; do
echo "Sorry, try again"
read trythis
done
exit 0
until 语句
#!/bin/sh
until who | grep "$1" > /dev/null
do
sleep 60
done
#now ring the bell and announce the expected user.
echo -e '\a'
echo "**** $1 has just logged in ****"
exit 0
case语句
#!/bin/sh
echo "Is it morning? please answer yes or no"
read timeofday
case "$timeofday" in
yes) echo "Good Morning";;
no ) echo "Good Afternoon";;
y ) echo "Good Morning";;
n ) echo "Good Afternoon";;
* ) echo "Sorry, answer not recognized";;
esac
exit 0
#!/bin/sh
echo "Is it morning? please answer yes or no"
read timeofday
case "$timeofday" in
yes | y | Yes | YES ) echo "Good Morning";;
n* | N* ) echo "Good Afternoon";;
* ) echo "Sorry, answer not recognized";;
esac
exit 0
#!/bin/sh
echo "Is it morning? please answer yes or no"
read timeofday
case "$timeofday" in
[yY] | [Yy][Ee][Ss] )
echo "Good morning"
echo "up bright and early this morning"
;;
[Nn]*)
echo "Good afternoon"
;;
* )
echo "Sorry, answer not recognized"
echo "please answer yes or no"
exit 1
;;
esac
exit 0
命令列表
AND: 只有在前面所有的命令都执行成功的情况才执行下一条命令
#!/bin/sh
touch file_one
rm -f file_two
if [ -f file_one ] && echo "Hello" && [ -f file_two ] && echo " there"
then
echo "in if"
else
echo "in else"
fi
exit 0
OR: 执行一系列命令直到有一条命令成功为止, 后面的命令不再执行
函数
#/bin/sh
foo(){
echo "Function foo is executing"
}
echo "script starting"
foo
echo "script ended"
exit 0
命令
break命令
#!/bin/sh
rm -rf fred*
echo > fred1
echo > fred2
mkdir fred3
echo >fred4
for file in fred*
do
if [ -d "$file" ]; then
break;
fi
done
echo first direcory starting fred was $file
rm -rf fred*
exit 0
:命令
#!/bin/sh
rm -f fred
if [ -f fred ]; then
:
else
echo file fred did not exist
fi
exit 0
continue命令: continue 语句的数字参数指定要跳过的循环级别。如果提供的数字参数大于嵌套层数,则会跳过最外层的循环
for x in 1 2 3
do
echo before $x
continue 1
echo after $x
done
eval 命令
foo=10
x=foo
eval y='$'$x
echo $y
exec命令:用wall替换shell
exec wall "Thanks for all the fish"
expr命令:将参数当做一个表达式求值
x=`expr $x + 1`
x=$(expr $x + 1)
set, unset命令: 为shell设置参数变量
#!/bin/sh
echo the date is $(date)
set $(date)
echo The month is $2
exit 0
trap命令: 捕捉信号
#!/bin/sh
trap 'rm -f /tmp/my_tmp_file_$$' INT # 接收中断信号SIGINT
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$ # 当前日期时间写入my_tmp_file_$$
echo "press interrupt (CTRL-C) to interrupt...."
while [ -f /tmp/my_tmp_file_$$ ]; #检查临时文件是否存在
do
echo File exists
sleep 1
done
echo The file no longer exists
trap INT #恢复对中断信号(SIGINT)的默认处理方式
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$
echo "press interrupt (control-C) to interrupt...."
while [ -f /tmp/my_tmp_file_$$ ];
do
echo File exists
sleep 1
done
echo we never get here
exit 0
命令的执行
语法: $(command) 或 `command`
echo The current directory is $PWD
echo The current user are $(who)
算术扩展: 使用$((...))完成简单的算术运算
#!/bin/sh
x=0
while [ "$x" -ne 10 ];
do
echo $x
x=$(($x+1))
done
exit 0
参数扩展
#!/bin/sh
unset foo #删除变量 foo,如果存在的话
echo ${foo:-bar} #输出为 "bar"
foo=fud
echo ${foo:-bar} #输出为 "fud"
foo=/usr/bin/X11/startx
echo ${foo#*/} #删除匹配的最短字符串,这里是 "*/",即删除第一个斜杠及其之前的内容
echo ${foo##*/} #删除的是最长匹配的字符串
bar=/usr/local/etc/local/networks
echo ${bar%local*} #末尾删除匹配的最短字符串
echo ${bar%%local*} #末尾删除的是最长匹配的字符串
exit 0
运行
bar
fud
usr/bin/X11/startx
startx
/usr/local/etc/
/usr/
here文档:允许我们在脚本中直接输出多行文本,无需使用 echo 命令或多个字符串
#!/bin/sh
cat <<!FUNCY! # 指定了 Here 文档的结束标记
hello
this is a here
document
!FUNCY! # 结束标记
dialog工具
创建一个简单的消息框:
dialog --msgbox "Hello World" 9 18
创建标题"check me"复选框:
dialog --title "Check me" --checklist "Pick Numbers" 15 25 3 1 "one" "off" 2 "two" "on" 3 "three" "off"
- 标题:Check me
- 类型:checklist
- 提示信息:Pick Numbers
- 高15行 宽25行 3个选项
- 编号:1 文本:one 状态: off
一个复杂的dialog工具
#!/bin/sh
# ask some questions and collect the answer
dialog --title "Questionnaire" --msgbox "Welcome to my simple survey" 9 18
dialog --title "Comfirm" --yesno "Are you willing to take part?" 9 18
if [ $? != 0 ];
then
dialog --infobox "Thank you anyway" 5 20
sleep 2
dialog --clear
exit 0
fi
dialog --title "Questionnaire" --inputbox "Please enter your name" 9 30 2>_1.txt
Q_NAME=$(cat _1.txt)
dialog --menu "$Q_NAME, what music do you like best?" 15 30 4 1 "Classical" 2 "Jazz" 3 "Country" 4 "Other" 2>_1.txt
Q_MUSIC=$(cat _1.txt)
if [ "$Q_MUSIC" = "1" ];
then
dialog --title "Likes Classical" --msgbox "Good choice!" 12 25
else
dialog --title "Doesn't like Classical" --msgbox "Shame" 12 25
fi
sleep 2
dialog --clear
exit 0