您的位置:首页 > 运维架构 > Shell

shell脚本 (实例演示--自己试验下)

2016-04-05 18:06 316 查看
shell脚本

查看Linux所支持的shell
# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh

输入/输出设备文件
/dev/stdin 标准输入设备 0
/dev/stdout 标准输出设备 1
/dev/stderr 标准错误输出设备 2

重定向
输出重定向
> >> 仅能重定向标准输出
2> 仅能重定向标准错误输出
&> 同时重定向标准输出及标准错误
输出重定向的特殊文件: /dev/null

输入重定向
<

输出语句
1、echo

# echo "hello world" 默认换行
hello world

选项:
-n:不换行
# echo -n "hello world"
hello world

-e
# echo -e "hello\tworld\t123"
hello world 123

\t:Tab空白
\n:换行、回车

单引号、双引号的区别
单引号:所有字符失去其特殊含义
双引号:具有特殊含义的字符会被转义

2、printf
# printf "hello world"
hello world

3、HERE DOCUMENT 用于输出多条信息
# cat << eof
> 1
> 22
> 333
> 4444
> eof

交互式命令的应用

1、passwd
# echo "redhat" | passwd --stdin tom &> /dev/null

# echo -e "n\np\n1\n\n+500M\nw\n" | fdisk /dev/sdb &> /dev/null

变量
自定义变量
特殊变量
环境变量

自定义变量

1、声明变量
# 变量名称=变量值

变量值全作为普通字符处理

2、引用变量的值
$变量名称
${变量名称}

3、使用变量的值进行数学运算
运算符:+ - * /(整除) %(取余)

方法1:$((expression))
# a=10
# b=20
# c=$((a+b))
# echo $c
30

方法2:$[expression]
# c=$[$a+$b]
# echo $c
30

方法3:关键字 let
# let c=a+b
# echo $c
30

方法4:关键字 declare
# declare -i c=a+b
# echo $c
30

4、将命令的执行结果赋予变量
`command` 反引号
$(command)

# a=`ls -ldh /dev`
# a=$(ls -ldh /dev)
# echo $a
drwxr-xr-x. 18 root root 3.2K Jan 24 22:32 /dev

5、删除变量
# unset 变量名称

特殊变量
$? 代表上一条命令的执行状态值
0---255:
0:上一条命令执行成功

环境变量

1、查看环境变量
# env
XDG_SESSION_ID=1
HOSTNAME=server.bj.com
SELINUX_ROLE_REQUESTED=
TERM=xterm

2、声明环境变量
# export 变量名称=变量值
/etc/profile
/etc/bashrc

3、修改环境变量的值
# export 变量名称=new_value

awk
按照指定分隔符分割文本内容
默认以空白字符作为分隔符
# awk '{print $1,$4}' /1.txt
this line.
this line.

选项: -F 用于指定分隔符

# awk -F: '{print $1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin

编写脚本的步骤:
1、新建脚本文件 *.sh
2、编写脚本内容
3、赋予脚本执行权限

编写脚本,实现创建用户userA,并为用户设置初始密码为123456,创建完成后给用户相应提示
#!/bin/bash
#
read -p "please input username: " name

useradd $name
echo "123456" | passwd --stdin $name &> /dev/null
echo "$name create finished,the default password is 123456"

编写脚本,实现配置本地yum源
#!/bin/bash
#

mount /dev/cdrom /mnt &> /dev/null

cat << eof > /etc/yum.repos.d/server.repo
[local]
name=localyum
baseurl=file:///mnt
enabled=1
gpgcheck=0
eof

yum repolist all &> /dev/null
yum makecache

分支语句---------if/case

if语句:

结构1:
if condition; then
statement1
statement2
....
fi

condition格式:
test expression
[ expression ]
` expression `
command 判断命令的执行状态

条件表达式:
数字判断
字符判断
文件/目录判断

数字判断:
[ number1 -eq number2 ] =
[ number1 -ne number2 ] !=
[ number1 -gt number2 ] >
[ number1 -ge number2 ] >=
[ number1 -lt number2 ] <
[ number1 -le number2 ] <=

编写脚本,由用户输入用户名,如果用户不存在,则创建该用户,并设置初始密码为123456,创建完成后,提示用户创建完成
#!/bin/bash
#

read -p "please input username for create: " name

grep "^$name:" /etc/passwd &> /dev/null
result=$?

if [ $result -ne 0 ];then
useradd $name
echo "123456" | passwd --stdin $name &> /dev/null
echo "$name create successful,the default password is 123456"
fi

#!/bin/bash
#

read -p "please input username for create: " name

if ! grep "^$name:" /etc/passwd &> /dev/null;then
useradd $name
echo "123456" | passwd --stdin $name &> /dev/null
echo "$name create successful,the default password is 123456"
fi

结构2:单分支if判断
if condition;then
statement1
statement2
...
else
statement1
statement2
...
fi

编写脚本,由用户输入用户名,如果用户不存在,则创建该用户,并设置初始密码为123456,并要求用户每一次登录系统时必须更改密码。创建完成后,提示用户创建完成;如果用户存在,显示用户已经存在
#!/bin/bash
#

read -p "please input username: " name

if id $name &> /dev/null;then
echo "$name has benn exists..."
else
useradd $name
echo "123456" | passwd --stdin $name &> /dev/null
passwd -e $name &> /dev/null
echo "$name create successfully,the default password is 123456"
fi

编写脚本,由用户输入名,判断用户的uid与gid是否一致,如果相同,则显示"good user",否则显示"bad user"

#!/bin/bash
#

read -p "please input username: " name

user_id=`grep "^$name:" /etc/passwd | awk -F: '{print $3}'`
group_id=`grep "^$name:" /etc/passwd | awk -F: '{print $4}'`

if [ $user_id -eq $group_id ];then
echo "Good user..."
else
echo "Bad user...."
fi
================================================================================
#!/bin/bash
#

read -p "please input username: " name

user_id=`id -u $name`
group_id=`id -g $name`

if [ $user_id -eq $group_id ];then
echo "Good user..."
else
echo "Bad user...."
fi

编写脚本,由用户输入用户名,判断用户是否存在,如果不存在,就显示用户不存在,如果存在,以下面格式输出用户相关信息:
UserName:
HomeDir:
Shell:

#!/bin/bash
#

read -p "please input username: " name

if id $name &> /dev/null; then
homedir=`grep "^$name:" /etc/passwd | awk -F: '{print $6}'`
usersh=`grep "^$name:" /etc/passwd | awk -F: '{print $7}'`
echo "UserName: $name"
echo "HomeDir: $homedir"
echo "UserShell: $usersh"
else
echo "$name not exist...."
fi

字符判断:
[ str1 == str2 ]
[ str1 != str2 ]
[ -z str1 ] 空串

shell脚本中对字符串的处理

1、${#变量名}
作用:返回字符串的长度
# foo="this is a test"
# echo ${#foo} //返回字符串foo的长度
14

2、${变量名:offset:length}
作用:截取字符串,length指定截取的长度,也可以不写;字符串的第一个字符的索引值为0
# foo="abcdefg"
# echo ${foo:3:2} //从下标为3的字符开始截取,共截取2个
de
# echo ${foo:3} //从下标为3的字符开始截取到最后的字符
defg

3、${变量名#pattern} ${变量名##parttern}
pattern:模式,通配符表达式
作用:清除字符串中符合pattern的字符
# foo="file.txt.zip"
# echo ${foo#*.} //一个#号代表按照最短匹配清除
txt.zip
# echo ${foo##*.} //2个#号代表按照最长匹配清除
zip

4、${变量名%pattern} ${变量名%%parttern}
pattern:模式,通配符表达式
作用:清除字符串中符合pattern的字符,从字符串最后匹配
# echo $foo
file.txt.zip
# echo ${foo%.*} //1个%代表按照最短匹配
file.txt
# echo ${foo%%.*} //2个%%代表按照最长匹配
file

5、字符串替换操作
${变量名称/old/new}
# foo="txt.txt"
# echo ${foo/txt/TXT} 替换第1次出现的txt
TXT.txt
# echo ${foo//txt/TXT} 替换字符串中所有的txt
TXT.TXT
# echo ${foo/#txt/TXT} 只替换字符串中开头的txt
TXT.txt
# echo ${foo/%txt/TXT} 只替换字符串中结尾的txt
txt.TXT

6、实现大小写字母的转换
# foo="ABde"
# echo ${foo,,} //将字符串foo全部转换成小写
abde
# echo ${foo,} //将字符串foo的第1个字符转换成小写
aBde
# echo ${foo^} //将字符串foo的第1个字符转换成大写
ABde
# echo ${foo^^} //将字符串foo全部转换为大写
ABDE

文件/目录判断
[ -e filename ] 文件是否存在
[ -f filename ] 是否为普通文本文件
[ -d filename ] 是否为目录
[ -r filename ] 是否拥有r权限
[ -w filename ] 是否拥有w权限
[ -x filename ] 是否拥有x权限

结构3:多if分支
语法 :
if condition;then
statement1
statement2
...
elif condition;then
statement1
statement2
...
elif condition;then
statement1
statement2
...
else
statement1
statement2
...
fi

编写脚本,由用户输入文件名,判断文件类型:
.txt this is a ASC text
.exe this is windows execute program
.so this is a libirary file

#!/bin/bash
#

file_type1="txt"
file_type2="exe"
file_type3="so"

read -p "please input filename: " file
type=${file##*.}

if [ $type == $file_type1 ];then
echo "This is a ASC text"
elif [ $type == $file_type2 ];then
echo "This is Windows EXECUTE Program"
elif [ $type == $file_type3 ];then
echo "This is Linux Libirary File"
else
echo "Unknown........"
fi

使用逻辑运算符同时判断多个条件:
And: [ condition1 -a condition2 ] [ condition1 ] && [ condition2 ]
Or: [ condition1 -o condition2 ] [ condition1 ] || [ condition2 ]

编写脚本,取出系统时间的小时数,对数据进行判断:
6--10 this is morning
11-13 this is noon
其他 this is night

#!/bin/bash
#

hour=`date +%H`

if [ $hour -ge 6 ] && [ $hour -le 10 ];then
echo "This is morning..."
elif [ $hour -ge 11 ] && [ $hour -le 13 ];then
echo "This is noon...."
else
echo "This is night..."
fi

结构4:嵌套if
语法:
if condition; then
if condition;then
statement1
statement2
....
else
statement1
statement2
...
fi
else
statement1
statement2
...
fi

编写脚本,判断用户的UID及GID,如果相同则显示"Good User.....",否则显示"Bad User........"
#!/bin/bash
#

read -p "please input username: " name

if id $name &> /dev/null;then
user_id=`id -u $name`
group_id=`id -g $name`
if [ $user_id -eq $group_id ];then
echo "Good user...."
else
echo "Bad user...."
fi
else
echo "$name not exist...."
fi

编写脚本,由用户输入一个文件名,判断该文件是否存在,如果存在,再判断文件中是否存在空白行,则显示该文件中空白行的行数,没有空行,则显示文件内容,并在每行前加入行号;如果不存在,则显示文件不存在
#!/bin/bash
#

read -p "please input filename: " file_name

if [ -f $file_name ];then
if grep "^$" $file_name &> /dev/null;then
line=`grep "^$" $file_name | wc -l`
echo "The number of null line is $line"
else
echo "The content of $file_name: "
cat -n $file_name
fi
else
echo "$file_name not exist..."
fi

编写脚本,配置本地yum源
光盘:挂载,取出挂载点目录
未挂载,由用户输入目录名称,并挂载

生成yum源配置文件:
用户手工输入yum源配置文件名称
存在, 追加yum源信息
不存在,创建文件,并生成yum源配置信息

#!/bin/bash
#

# /dev/cdrom

if mount | grep iso9660 &> /dev/null;then
cdrom_dir=` mount | grep iso9660 | cut -d' ' -f3`
else
read -p "please input directory : " cdrom_dir
if [ -d $cdrom_dir ];then
mount /dev/cdrom $cdrom_dir &> /dev/null
else
mkdir -p $cdrom_dir
mount /dev/cdrom $cdrom_dir &> /dev/null
fi
fi

#Edit yum config file

read -p "please input yum config file: " file
if [ -f /etc/yum.repos.d/$file ];then
echo "[local]" >> /etc/yum.repos.d/$file
echo "name=localyum" >> /etc/yum.repos.d/$file
echo "baseurl=file://$cdrom_dir" >> /etc/yum.repos.d/$file
echo "enabled=1" >> /etc/yum.repos.d/$file
echo "gpgcheck=0" >> /etc/yum.repos.d/$file
else
echo "[local]" > /etc/yum.repos.d/$file
echo "name=localyum" >> /etc/yum.repos.d/$file
echo "baseurl=file://$cdrom_dir" >> /etc/yum.repos.d/$file
echo "enabled=1" >> /etc/yum.repos.d/$file
echo "gpgcheck=0" >> /etc/yum.repos.d/$file
fi

分支判断语句-------case

语法:
case 变量 in
value1)
statement1
statement2
;;
value2)
statement1
statement2
;;
value3)
statement1
statement2
;;
*)
statement1
statement2
;;
esac

编写脚本,判断用户输入的字符

特殊字符集:
[:alnum:] 所有字母及数字
[:alpha:] 所有字母
[:digit:] 所有数字
[:lower:] 所有小写字母
[:upper:] 所有大写字母

#!/bin/bash
#

read -p "please input a char: " char

case $char in
[[:lower:]]*)
echo "This is lower."
;;
[[:upper:]]*)
echo "This is upper."
;;
[[:digit:]]*)
echo "This is number."
;;
*)
echo "This is special char."
;;
esac

特殊变量:
$? 返回上一条命令的执行状态
0---255:
0代表成功
其他代表失败

位置变量:
$1,$2,$3,$4........$9,${10}
$1代表命令的第1个参数,依次类推
$0: 代表命令本身
$#: 命令参数的个数

编写脚本,判断第1个参数,如果是linux则显示Windows,如果是windows,则显示Linux,其他则显示Other

#!/bin/bash
#

if [ $# -ne 1 ];then
echo "Usage: `basename $0` { linux | windows | other }"
exit 7
fi

case $1 in
linux)
echo "Windows..."
;;
windows)
echo "Linux...."
;;
*)
echo "Other...." >& 2
;;
esac

编写脚本,用户在执行脚本时,输入一个用户名作为参数,如果用户不输入,则显示该脚本的用法;否则判断该用户是否存在,存在则删除并删除其宿主目录,删除完成后提示用户删除成功,否则显示用户不存在

#!/bin/bash
#

if [ $# -ne 1 ];then
echo "Usage: `basename $0` <username>"
exit 9
fi

if id $1 &> /dev/null;then
userdel -r $1
echo "$1 has been delete..."
else
echo "$1 not exist........"
fi

函数的使用

1、声明函数

方法1:
function_name() {
statement1
statement2
....
}

方法2:
function function_name {
statement1
statement2
....
}

2、调用函数
function_name

在函数中使用位置变量,向函数传递参数

编写脚本,提供给用户功能菜单,包括创建目录及删除目录,根据用户的需求分别实现创建、删除目录功能,创建、删除目录的功能使用函数实现
This tool provide these function:
create directory(c|C)
delete direcotry(d|D)
quit(q|Q)

#!/bin/bash
#

createdir() {
read -p "please input dir name: " dir
if [ ! -d $dir ];then
mkdir -p $dir
echo "$dir has benn create finished"
else
echo "$dir has been exist"
fi
}

deldir() {
if [ -d $1 ];then
rm -rf $1
echo "$1 has benn delete finished"
else
echo "$1 not exist"
fi
}

showmenu() {
cat << EOF
This tool provide these function:
create directory(c|C)
delete direcotry(d|D)
quit(q|Q)
EOF
}

showmenu
read -p "please select a tools: " tool

case $tool in
c|C)
createdir
;;
d|D)
read -p "please input dir name: " dir
deldir $dir
;;
q|Q)
echo "Thanks"
exit 0
;;
*)
showmenu
exit 8
;;
esac

编写脚本
列出如下功能菜单:
provide these tools:
Add user(A|a)
Del user(D|d)
Modify user(M|m)
quit(Q|q)

A|a 创建用户,并为用户设置初始密码为123456
D|d 删除用户,提示输入用户名
M|m 修改用户的shell,提示输入用户名;用户的旧shell名称显示出来,再提示输入新的shell程序,
q|Q 退出脚本 Thank you…….

#!/bin/bash

cat << EOF
provide these tools:
Add user(A|a)
Del user(D|d)
Modify user(M|m)
quit(Q|q)
EOF

createuser() {
read -p "please input username: " name
if ! id $name &> /dev/null;then
useradd $name
echo "123456" | passwd --stdin $name &> /dev/null
echo "$name create finished,the default password is 123456"
else
echo "$name alread exists....."
fi
}

deleteuser() {
if id $1 &> /dev/null;then
userdel -r $1
echo "$1 has been delete!"
else
echo "$1 not exist...."
fi
}

modifyuser() {
echo "The shell programm of OS support: "
cat -n /etc/shells
read -p "please input new shell: " new_sh
usermod -s $new_sh $1
echo "The shell of $1 has been modified to $new_sh"
}

read -p "please select a tool: " choice
case $choice in
A|a)
createuser
;;
D|d)
read -p "please input username: " name
deleteuser $name
;;
M|m)
read -p "please input username: " name
if id $name &> /dev/null;then
old_sh=`grep "^$name:" /etc/passwd | cut -d: -f7`
echo "$name old shell is $old_sh"
else
echo "$name not exist...."
exit 7
fi
modifyuser $name
;;
Q|q)
echo "Thank you ..."
exit 0
esac

循环

注意:
1、循环开始的条件
2、循环终止的条件

循环语句-------------for/while/until

for语句结构:

for 变量 in 取值; do
statement1
statement2
...
done

取值范围:
字符
不同的字符使用空格隔开;字符中有空格时需要使用双引号
数字
1 2 3
{1..100}
seq 5, seq 2 5, seq 1 2 5

编写脚本,计算100内所有偶数的和
#!/bin/bash
#

sum=0
for i in `seq 0 2 100`;do
sum=$((sum+i))
done
echo $sum

#!/bin/bash
#

sum=0
for i in {1..100};do
yu=$((i%2))
if [ $yu -eq 0 ];then
sum=$((sum+i))
fi
done

echo $sum

文件 cat /1.txt
以空白字符区分行

编写脚本,在文件中存储用户名,批量创建用户,并为用户设置初始密码为123456,用户第一次登录系统需要更改密码

#!/bin/bash
#

for i in `cat /username.txt`;do
useradd $i
echo "123456" | passwd --stdin $i &> /dev/null
passwd -e $i &> /dev/null
echo "$i create finished,the default password is 123456"
done

编写脚本,向系统中所有用户打招呼
#!/bin/bash
#

line=`wc -l /etc/passwd | cut -d' ' -f1`

for i in `seq $line`;do
name=`head -$i /etc/passwd | tail -1 | cut -d: -f1`
echo "Hi $name"
done

编写脚本, 检测在线主机状态
#!/bin/bash
#

network=10.1.1.

for i in {1..254};do
if ping -c 1 -W 1 $network$i &> /dev/null;then
echo "Host $network$i is up"
else
echo "Host $network$i is down"
fi
done

编写脚本, 分别统计/sbin/nologin的用户个数及/bin/bash用户的个数

#!/bin/bash
#

bnumber=0
snumber=0

line=`wc -l /etc/passwd | awk '{print $1}'`

for i in `seq $line`;do
sh=`head -$i /etc/passwd | tail -1 | awk -F: '{print $7}'`
case $sh in
"/bin/bash")
bnumber=$((bnumber+1))
;;
"/sbin/nologin")
snumber=$((snumber+1))
;;
esac
done
echo "The number of user whose shell is /bin/bash: $bnumber"
echo "The number of user whose shell is /sbin/noglogin: $snumber"

中断循环语句:
break :结束整个循环
continue:结束本次循环,开始下一次循环

编写脚本,计算1到100的和,输出和为3000时的被加数
#!/bin/bash
#

sum=0

for i in {1..100};do
let sum=sum+i
if [ $sum -ge 3000 ];then
break
fi
done

编写脚本,取出系统中shell为/bin/bash的前5个用户
#!/bin/bash
#

count=0
line=`wc -l /etc/passwd | awk '{print $1}'`

for i in `seq $line`;do
sh=`head -$i /etc/passwd | tail -1 | awk -F: '{print $7}'`
if [ $sh == "/bin/bash" ];then
name=`head -$i /etc/passwd | tail -1 | awk -F: '{print $1}'`
echo -n "$name "
let count++
fi
if [ $count -eq 5 ];then
break
fi
done

循环结构2:

while condition;do
statement1
statement2
....
change_condition_statement
done

while循环中必须存在一条可以改变循环条件的语句

编写脚本,利用while循环计算1---100的和
#!/bin/bash
#

sum=0
i=1

while [ $i -le 100 ];do
let sum=sum+i
let i++
done

echo $sum

编写脚本,由用户输入数字,数字为8时中止循环,否则不停地输入
#!/bin/bash
#

read -p "please input a number: " num

while [ $num -ne 8 ];do
read -p "please input a number: " num
done

echo "Congratiulation..."

编写脚本,检测脚本文件语法
#!/bin/bash
#

bash -n $1 &> /dev/null
result=$?

while [ $result -ne 0 ];do
vim + $1
bash -n $1 &> /dev/null
result=$?
done

编写脚本,功能菜单
provide these tools:
show disk info(d)
show mem info(m)
show cpu info(c)
quit(q)

#!/bin/bash
#

showmenu() {
cat << eof
provide these tools:
show disk info(d)
show mem info(m)
show cpu info(c)
quit(q)
eof
}

showmenu
echo
read -p "please select a tool: " choice

while [ $choice != q ];do
case $choice in
d)
echo "===========The info of disk============="
df -hT
;;
m)
echo "==========The info of memory============"
free -m
;;
c)
echo "=========The info of CPU================"
uptime
;;
*)
echo "sorry,we don't provide this tool,your choice is wrong"
showmenu
;;
esac
read -p "please input select a tool: " choice
done

while特殊用法:
用法1:
while true;do
statement1
statement2
....
done

编写脚本,每5秒钟显示一次CPU负载
#!/bin/bash
#

while true;do
uptime
sleep 5
done

用法2:
while read line;do
statement1
statement2
....
done < file

将文件中的每一行赋予变量line,执行循环操作

#!/bin/bash
#

while read line;do
name=`echo $line | awk -F: '{print $1}'`
echo "Hi, $name"
done < /etc/passwd

循环结构3-------util
util condition;do
statement1
statement2
...
change_condition_statement
done

条件为假,执行循环;条件为真,退出循环

array: 数组

一段连续的内存空间
数组的下标从0开始

1、声明一个数组
# declare -a array

2、数组元素赋值方法
方法1:
array[0]=tom
array[1]=jerry
array[2]=mike
array[6]=natasha

方法2:
array=(tom jerry mike)
array=([0]=tom [1]=jerry [6]=mike)
数组下标可以不连续,但在下标6之前的元素会被初始化为空值
如果某个元素值中有空格,需要使用双引号

显示数组中所有元素
${array_name[*]}
${array_name[@]}

3、引用数组元素的值
${array
}
n: 数组下标

# array=([0]=tom [1]=jerry [6]=mike)
# echo ${array[1]}
jerry

4、显示数组中下标为n的元素的字符长度
${#array
}

# array=([0]=tom [1]=jerry [6]=mike)
# echo ${#array[6]}
4

5、显示数组中值不为空的元素的个数
${#array[*]} 或者 ${#array[@]}

# array=([0]=tom [1]=jerry [6]=mike)
# echo ${#array[*]}
3

编写脚本,找出数组中最大值
#!/bin/bash
#

read -p "please input length of array : " len

for i in `seq 0 $len`;do
number[$i]=$(($RANDOM%100))
done
echo ${number[*]}

max=${number[0]}
count=${#number[*]}

for i in `seq $((count-1))`;do
if [ ${number[i]} -gt $max ];then
max=${number[i]}
fi
done

echo "The max number is $max"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hello 单引号 双引号