变量
内建变量 解释
$0 命令行中的脚本名字
$1 第一个命令行参数
$2 第二个命令行参数
….. …….
$9 第九个命令行参数
$# 命令行参数的数量
$* 所有命令行参数,以空格隔开
三种引号
强引用
弱引用
命令引用
read
从键盘读取变量的值,通常用在 shell 脚本中与用户进行交互的场合。该命令可以一次读取多个变量的值,变量和输入的值都需要使用空格隔开。在 read 命令后面,如果没有指定变量名,读取的数据将被自动赋值给特定的变量REPLY
read a
echo a
提示
read -p "请输入" $OP
流程控制
if []; then
command1
fi
多分支 if 语句
if []; then
command1
elif []; then
c2
else
fi
test测试
数值比较
等于则为真
$a -eq $b
不等于则为真
-ne
大于则为真
-gt
大于等于则为真
-ge
小于则为真
-lt
小于等于则为真
-le
字符串比较
等于则为真
==
不相等则为真
!=
字符串的长度为零则为真
-z
字符串的长度不为空则为真
-n
str1 大于 str2 为真
str1 小于 str2 为真
<
文件比较
如果文件或目录存在则为真
-e
如果文件存在且可读则为真
-r
如果文件存在且可写则为真
-w
如果文件存在且可执行则为真
-x
如果文件存在且至少有一个字符则为真
-s
如果文件存在且为目录则为真
-d
如果文件存在且为普通文件则为真
-f
如果文件存在且为字符型文件则为真
-c
如果文件存在且为块特殊文件则为真
-b
检查 file1 是否比 file2 新
file1 -nt file2
检查 file1 是否比 file2 旧
file1 -ot file2
流程控制过程中复杂条件
[]&&[] []||[]
[ -a ] [ -o ]
[[ && ]] [[ || ]]
[[ … ]] [ … ]
[[… ]]能够支持 *,< 、>等符号且不需要转义符
shell 中的通配符
匹配 0 或多个字符
匹配任意一个字符
?
匹配 list 中的任意单一字符
[list]
匹配 除 list 中的任意单一字符
[!list]
匹配 c1-c2 中的任意单一字符 如:[0-9] [a-z]
[c1-c2]
匹配 sring1 或 string2 (或更多)其一字符串
{string1,string2,…}
case
case $a in
1|backup)
echo "1"
;;
2|copy)
echo "2"
;;
*)
echo "default"
esac
循环
for
for var in list ; do
done
取值列表有多种取值方式
列表中的复杂值,可以使用 引号或转义字符”/”来加以约束
从变量中取值
从命令中取值
自定义 shell 分隔符
默认情况下,base shell 会以空格、制表符、换行符做为分隔符。通过 IFS 来自定义为分隔符
指定单个字符做分隔符:
IFS=: #以:冒号做分隔符
可以指定多个
如 IFS='\n':;" #这个赋值会将反斜杠、n、冒号、分号和双引号作为字段分隔符。
注:$'\n'与'\n'时的区别
IFS='\n' #将字符\和字符 n 作为 IFS 的换行符。
IFS=$'\n' #正真的使用换行符做为字段分隔符。
列:以:冒号做分隔符
#!/bin/bash
IFS=:
list = `head -1 /etc/passwd`
for $i in list; do
echo $i
done
C 语言风格的 for
例 1:单个变量。 输出 1 到 10 之间的数字
#!/bin/bash
for ((i=1;i<=10;i++)); do
echo $i
done
while
while []
do
done
braek
continue
shift
函数
function name {
commands
}
name {
commands
}
面试题
Q:1 Shell脚本是什么、它是必需的吗?
Q:2 什么是默认登录shell,如何改变指定用户的登录shell
chsh
Q:3 可以在shell脚本中使用哪些类型的变量?
Q:4 如何将标准输出和错误输出同时重定向到同一位置?
2>&1 &>
Q:5 shell脚本中“if”语法如何嵌套?
if []; then
f1
else
if []; then
f2
fi
fi
Q:6 shell脚本中“$?”标记的用途是什么?
0 success
Q:7 在shell脚本中如何比较两个数字 ?
#!/bin/bash
$a = 1
$b = 2
if [$a -gt $b]; then
echo 1
else
echo 2
fi
Q:8 shell脚本中break命令的作用 ?
Q:9 shell脚本中continue命令的作用 ?
Q:10 告诉我shell脚本中Case语句的语法 ?
case $OP in
1)
echo "1"
;;
2)
echo "2"
;;
*)
echo "d"
esac
Q:11 shell脚本中while循环语法 ?
while []
do
f1
done
Q:12 如何使脚本可执行 ?
+x
Q:13 “#!/bin/bash”的作用 ?
释伴行
Q:14 shell脚本中for循环语法 ?
for var in list; do
done
Q:15 如何调试shell脚本 ?
- sh -x 脚本
- sh -nv 脚本(存疑)
Q:16 shell脚本如何比较字符串?
Q:17 Bourne shell(bash) 中有哪些特殊的变量 ?
Q:18 在shell脚本中,如何测试文件 ?
Q:19 在shell脚本中,如何写入注释 ?
Q:20 如何让 shell 就脚本得到来自终端的输入?
Q:21 如何取消变量或取消变量赋值 ?
unset
Q:22 如何执行算术运算 ?
- uxpr 5 + 2
- $[5 + 2]
Q:23 do-while语句的基本格式 ?
do {
command
} while (条件)
Q:24 在shell脚本如何定义函数呢 ?
function name {
}
name {
}
Q:25 获取随机字符串或数字
获取随机8位字符串:
#!/bin/bash
echo $RANDOM | md5sum | cut -c 1-8
openssl rand -base64 4
cat /proc/sys/kernel/random/uuid | cut -c 1-8
获取随机8位数字:
echo $RANDOM | cksum | cut -c 1-8
openssl rand -base64 4 | cksum | cut -c 1-8
date +%N | cut -c 1-8
cksum:打印CRC效验和统计字节
Q:26 定义一个颜色输出字符串函数
方法1:
function echo_color() {
if [ $1 == "green" ]; then
echo -e "\033[32;40m$2\033[0m"
elif [ $1 == "red" ]; then
echo -e "\033[31;40m$2\033[0m"
fi
}
方法2:
function echo_color() {
case $1 in
green)
echo -e "\033[32;40m$2\033[0m"
;;
red)
echo -e "\033[31;40m$2\033[0m"
;;
*)
echo "Example: echo_color red string"
esac
}
使用方法:echo_color green "test"
Q:27 批量创建用户
#!/bin/bash
DATE=$(date +%F_%T)
USER_FILE=user.txt
echo_color() {
if [ $1 == "green" ]; then
echo -e "\033[32;40m$2\033[0m"
elif [ $1 == "rad" ]; then
echo -e "\033[31;40m$2\033[0m"
fi
}
# 如果用户文件存在并且大小大于0就备份
if [ -s $USER_FILE ]; then
mv $USER_FILE ${USER_FILE}-${DATE}.bak
echo_color green "USER_FILE exist, rename ${USER_FILE}-${DATE}.bak"
fi
echo -e "user\tPassword" >> $USER_FILE
echo "------------" >> $USER_FILE
for USER in user{1..10}; do
if ! id $USER &>/dev/null; then
PASS = $(echo $RANDOM | md5sum | cut -c 1-8)
useradd $USER
echo $PASS | passwd --stdin $USER &> /dev/null
echo -e "$USER\t$PASS" >> $USER_FILE
echo "$USER User create successful."
else
echo_color red "$USER User already exists!"
fi
done
常见脚本
#!/bin/bash # 告诉脚本使用的是哪种命令解释器。如不指shell,以当前shell作为执行的shell
# 自动备份mariadb
BACKDIR=/data/backup/mysql/`date +%Y-%m-%d` #保存路径
MYSQLDB= #保存的数据库名
MYSQLUSER= #用户名
MYSQLPW= #密码
# 必须使用root用户运行,$UID为系统变量
if
[ $UID != 0 ];then
echo "不是root"
exit 0
fi
# 判断目录是否存在,不存在则新建
if
[ ! -d $BACKDIR ];then
mkdir -p $BACKDIR
echo "新建完成!"
else
echo "目录已存在!"
exit
fi
# 使用mysqldump 备份 mysql
/usr/bin/mysqldump -u$MYSQLUSER -p$MYSQLPW $MYSQLDB > $BACKDIR/${MYSQLDB}_db.sql
cd $BAKEDIR;tar -czf ${MYSQLDB}_db.tar.gz *.sql
# 删除sql文件
find $BACKDIR -type f -name *.sql -exec rm -rf {} \;
#find $BACKDIR -type f -nmae *.sql | xargs rm -rf
# 检查并冗余一次
[ $? -eq 0 ] && echo "`date +%Y-%m-%d备份成功`"
cd /data/backup/mysql/ && find . -type d -mtime +30 | xrags rm -rf
echo "备份完成"
#!/bin/bash
#chkconfig:2345 80 90
#description:niginx启动
#nginx启动脚本
#@auther syh
#@version 0.0.1
#@date 2021-1-8
PATH=/data/soft/nginx #nginx路径
DESC=“nginx daemon”
NAME=nginx
DAEMON=$PATH/sbin/$NAME
CONFIFILE=$PATH/$NAME.conf
PIDFILE=$PATH/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
[ -x "$DAEMON"] || exit 0
do_start()
{
$DAEMON -c $CONFIGFILE || echo -n "nginx已经在运行"
}
do_stop()
{
$DAEMON -s stop || echo -n "nginx已经关闭"
}
do_reload()
{
$DAEMON -s reload || echo -n "nginx不能重启"
}
case "$1" in
start)
echo -n "Starting $DESC:$NAME"
do_start
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME"
do_stop
echo "."
;;
reload|graceful)
echo -n "Reloading $DESC configuration..."
do_reload
echo "."
;;
restart)
echo -n "Restarting $DESC: $NAME"
do_stop
do_start
echo "."
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|reload|restart}" >&2
exit 3
;;
esac
exit 0