SHELL 笔记
2021-09-03 本文已影响0人
FyK_21f8
shell笔记
判断语句
# 判断字符串是否为空
if [ -z "${STR}" ];then
echo "STR IS NULL"
else
echo "STR IS NOT NULL, VALUE IS ${STR}"
fi
# 判断两个字符串是否相等
if [ "${STR}" == "${TARGET}" ];then
echo "EQUALS"
else
echo "NOT EQUALS"
fi
# 两个数字比较, -eq 相等, -ne 不相等, -gt 大于, -lt 小于, -ge 大于等于, -le 小于等于
if [ $NUM1 -eq $NUM2 ]; then
echo "$NUM1 = $NUM2"
elif [ $NUM1 -gt $NUM2 ]; then
echo "$NUM1 > $NUM2"
else
echo "$NUM1 < $NUM2"
fi
# 判断文件夹是否存在,不存在则创建
if [ -d ${DIR_PATH} ]; then
echo "${DIR_PATH} EARLY EXISTS"
else
echo "${DIR_PATH} NOT EXISTS, TRY TO MAKE DIR"
mkdir -p ${DIR_PATH}
fi
# 判断文件是否存在,不存在则创建
if [ -f ${FILE_PATH} ]; then
echo "${FILE_PATH} EARLY EXISTS"
else
echo "${FILE_PATH} NOT EXISTS, TRY TO TOUCH FILE"
touch ${FILE_PATH}
fi
运算
# 运算符 + - * / %
# 方法1,`expr ...`
RESULT=`expr ${NUM1} + ${NUM2}`
echo $RESULT
# 方法2,$(( ... ))
RESULT=$((${NUM1} / ${NUM2}))
echo $RESULT
选择语句
# if 语句
if [ ${NUM} -eq 1 ]; then
echo "${NUM1}等于1"
elif [ ${NUM} -gt 1 ]; then
echo "${NUM1}大于1"
else
echo "${NUM1}小于1"
fi
# case语句
PAY="weixin"
case "${PAY}" in
"weixin")
echo "微信支付"
;;
"alipay")
echo "支付宝支付"
;;
# 匹配多个 | 隔开
"card" | "bank")
echo "银行卡支付"
;;
*)
echo "其他支付方式"
;;
esac
循环语句
# 1 for
# 1.1 普通for
NUM=5
for (( INDEX=0; INDEX < $NUM; INDEX ++))
do
echo $INDEX
done
# 1.2 for in
for VAR in str1 str2 str3
do
echo $VAR
done
# while
while (( $NUM <= 15))
do
echo ${NUM}
# let 中执行表达式,使用变量不需要加上$
let "NUM++"
done
# 3 死循环
# 3.1 while true
while true
do
echo "loop"
done
# 3.2 while :
while :
do
echo "loop"
done
# for (( ; ; ))
for (( ; ; ))
do
echo "loop"
done
将shell字句执行结果复制给变量
# 方法1, ``
NOW_DATE_TIME=`date "+%Y-%m-%d %H:%M:%S"`
echo $NOW_DATE_TIME
# 方法2,$()
NOW_DATE_TIME=$(date "+%Y-%m-%d %H:%M:%S")
echo $NOW_DATE_TIME
shell简单传参
编号 | 变量符号 | 释义 |
---|---|---|
1 | $0 | 脚本的名称 |
2 | $n | 获取第n个参数的值 |
3 | $* | 获取所有的参数 |
4 | $# | 这个脚本执行时的入参个数 |
5 | $$ | 这个脚本执行时的PID |
6 | $@ | 和$*一样,但是能当做数组使用 |
字符串'',""的区别
# ''中的字符串会原封不动的输出,变量不会生效
STR="String"
FINAL_STR='${STR}'
echo $FINAL_STR
# 输出结果 ${STR}
# ""变量可生效
FINAL_STR="${STR}"
echo $FINAL_STR
# 输出结果 String
数组
# 定义数组
ARRAY=("NAME" "AGE" "ADDRESS")
# 修改数组的元素
ARRAY[0]="NIKE_NAME"
# 读取数组元素
ELEMENT_VALUE=${ARRAY[0]}
echo ${ELEMENT_VALUE}
# 获取数组长度
LENGTH_1=${#ARRAY[@]}
LENGTH_2=${#ARRAY[*]}
echo ${LENGTH_1} ${LENGTH_2}
# 遍历数组的3种方式
# 方法1
for element in ${ARRAY[@]}
do
echo $element
done
# 方法2
for (( int=0;int < ${#ARRAY[@]};int ++))
do
echo ${ARRAY[int]}
done
# 方法3
for index in "${!ARRAY[@]}"
do
echo ${ARRAY[$index]}
done
输入重定向
# 把打印结果HELLO WORD重定向到/home/a.txt中,文件不存在则创建,路径不存在报错
echo "HELLO WORD !" > /home/a.txt
# > 清空原文本后写入, >> 追加到文件尾部
# 以运行jar包命令为例子(这个应该经常用吧)
nuhup java -jar xxxxx.jar ${JAVA_OPTS} >/dev/null 2>&1 &
# nohup xxxx & 让程序后台运行
# >/dev/null ,正常nohup 运行会输出nohup.out日志文件,不想输出则将日志重定向到/dev/null这个文件中,无底洞
# 2>&1表示正常日志和错误日志输出文件合并,2为错误文件的描述符,1为标准文件输出的描述符
# >/dev/null 2>&1 表示合并后重定向到无底洞,一般不需要输出日志时使用
# 清空某个文件的快捷方式
echo "" > /path/file
文件属性
-rwxr-xr-x 1 root root 5051 Sep 3 14:56 execute_agg.sh
# 第一个字符 - 标识为文件类型,还有其他类型: d 为文件夹, l 为链接
# 接下来的字符以三个为一组,出现三组,每组均为rwx的组合(三个字母顺序不会变), r代表读(read),w代表写(write),x代表可执行(execute),对应的位置上有字母则标识有字母对应的权限,-代表没有权限.第一组表示该文件拥有者用户的权限,第二组是用户组的权限,第三组为其他用户的权限.
# 更改文件用户归属(-R 递归)
chown -R [用户名] [文件名或者文件夹]
# 更改所属组
chgrp -R [用户组名] [文件或者文件夹]
# 修改文件权限
# 其中u=rwx表示所有者的权限为可读可写可执行,依次类推g为用户组,o为其他用户,a为u,g,o都改变
chmod u=rwx,g=rw,o=r /home/a.txt
# 进修改某个用户的某个权限 chmod [u/g/o/a][+/-][r/w/x] [file_path]
chmod o+x /home/a.txt
# rwx也可以用数字表示简化权限设置, r=4,w=2,x=1;所以 r--=4, -w-=2, --x=1, rw-=6,r-x=5,-wx=3,rwx=7
chmod 777 /home/a.txt
磁盘相关
# 查看内存使用情况
free -h
# 查看磁盘使用情况
df -h
# 查看某个目录下所有文件的使用空间情况du -h [path], 查看当前目录[path]可忽略
du -h /home
# 如果不想递归展开,只查看当前文件夹层级(文件直接显示打下,文件夹显示文件夹内所有文件的大小总和) du -h [path/*],当前文件夹可忽略路径直接*
du -sh *
# 排序,这里不能加h,因为h将单位转换成KB/MB/GB会影响排序,后面还可以加 | head或者 | tail查看最后最顶部10条记录
du -s * | sort -nr
vim相关常用操作
功能 | 运行模式 | 命令 |
---|---|---|
搜索 | 命令模式/底行模式 | /[要搜索的内容] |
上一个搜索目标 | 进入搜索结果后 | N |
下一个搜索目标 | 进入搜索结果后 | n |
回到文档第一行 | 命令模式 | gg |
跳到文档最后一行 | 命令模式 | shift + g |
向上翻页 | 命令模式 | ctrl + b |
向下翻页 | 命令模式 | ctrl + f |
剪切光标所在行(可当删除一行用) | 命令模式 | dd |
复制光标所在行 | 命令模式 | yy |
粘贴剪切或复制的内容 | 命令模式 | p |
进入编辑模式 | 命令模式 | i |
回到命令模式 | 底行模式/编辑模式 | Esc |
进入底行模式 | 命令模式 | shift + : |
退出(有修改则无法退出) | 底行模式 | q |
不保存退出 | 底行模式 | q! |
保存退出 | 底行模式 | wq |
强制保存退出 | 底行模式 | wq! |
取消搜索结果的高亮显示 | 底行模式 | noh |
显示行号 | 底行模式 | set nu |
取消显示行号 | 底行模式 | set nonu |
yum安装软件
# 安装 -y 不需要询问直接安装
yum install -y xxxxx
# 删除
yum remove -y xxxxx
# 更新软件,如果不写软件名直接更新整个系统包括linux内核yum update xxxx# 只下载安装包不执行安装需要有downloadonly插件, yum install -y yum-download安装
yum install xxx -downloadonly -downloaddir=/home/installers
# 安装下载后的rpm包(需要先cd 到离线rpm包所在的目录)
yum localinstall *.rpm
# 或者使用
rmp -ivh *.rpm
awk字符串切割的使用
# awk -F '[分割符号]' '{print $n}', $n 代表第几个参数# 读取conf.properties中name=jack的值
NAME=`cat conf.properties | grep 'name' | awk -F '=' '{print $2}'`
echo ${NAME}
# 假设要kill flume这个应用
ps -ef | grep 'flume' | grep -v 'grep' | awk -F ' ' '{print $1}' | xargs -n kill -9
# 判断某个应用是否启动,没有启动则启动
ps -ef | grep docker | grep -v "grep"| wc -l
wc 用于计算字数
# wc 可配置参数, -l 统计行数, -w 统计词数# wc -l 计算行数,判断应用是否启动
DOCKER_COUNT=`ps -ef | grep docker | grep -v "grep"| wc -l`
if [ $DOCKER_COUNT -gt 0 ]; then
echo "docker is started"
else
systemctl start docker
fi
将某个字符串按照某个字符切割成数组
# 按照逗号进行分割
taskids="1001,1002,1003"TASK_IDS=${taskids//,/ }
大小写转换
STR="AbC"
# 大写转小写
STR=`echo $STR | tr 'A-Z' 'a-z'`
echo $STR
# 小写转大写
STR=`echo $STR | tr 'a-z' 'A-Z'`
echo $STR
日期转换操作
# 将date转换yyyy-MM-dd HH:mm:ss格式时间
CURRENT_DATE=`date "+%Y-%m-%d %H:%M:%S"`
echo "$CURRENT_DATE"
# 将yyyy-MM-dd HH:mm:ss格式时间转换成时间戳
END_TIME=`date -d "$CURRENT_DATE" +%s`
echo "${END_TIME}"
读取用户输入内容
# read会让用户进入输入模式,并使用变量接收用户输入值
echo "PLEASE INPUR YOUR NAME"
read NAME
echo ${NAME}
cp 命令直接覆盖文件不需要询问
# 在写shell脚本的时候执行cp命令,经常遇到文件存在时,提示是否需要覆盖,而导致脚本无法往下执行,centos 的cp执行的时候通过别名的方式会自动加上-i
# 要达到不需要询问直接覆盖,使用/使别名失效即可
\cp /home/a.txt /home/b.txt
sed -i 替换文件内容
a.txt文件内容
name:jack
namespace-name:dev-center
nick-name:tom
sed -i 操作
# s/xxx/xxx/,匹配第一个遇到的字符串
sed -i "s/name/nickname/" a.txt
# 修改后的文档结果
# nickname:jack
# nicknamespace-name:dev-center
# nick-nickname:tom
# s/xxx/xxx/g,匹配所有遇到的字符串
sed -i "s/name/nickname/g" a.txt
# 修改的文档结果
# nickname:jack
# nicknamespace-nickname:dev-center
# nick-nickname:tom
# s/^xxx/xxx/g,只匹配xxx开头的
sed -i "s/^name/nickname/g" a.txt
# 修改后的文档输出结果
# nickname:jack
# nicknamespace-name:dev-center
# nick-name:tom
# 将namespace-name:dev-center换成namespace-name:uat-center
sed -i "s/^namespace-name.*/namespace-name:uat-center/g" a.txt
# 如果匹配或者需要替换的字符串中,出现与分隔符一致的符号则会报错,需要换乘其他分隔符,如 #等
echo "http://www.baidu.com" >> a.txt | sed -i "s#http:.*#http://www.qq.com#g" a.txt
tee 读取将标准输入内容并将内容输入到文件
tee -a a.txt <<EOFaaabbbcccEOF
压缩解压
# 1 tar
# 1.1 tar压缩
tar -zcvf apps.tar.gz /apps
# 1.2 tar 解压 -C 后跟需要解压到什么位置, 忽略-C 则解压到当前文件
tar -zxvf apps.tar.gz -C /opt
# zip解压,解压window上传的zip包
unzip apps.zip
expect 自动交互套件
写脚本中经常需要自动处理一些交互的内容,比如自动登录等,需要有expect套件,yum -y install expect安装
# 添加用户的操作
USERNAME="admin"
PASSWORD="123456"
expect << EOF
# 执行超时时间
set timeout 5
# spawn后面跟需要执行的命令
spawn useradd $USERNAME
expect "#"
set timeout 10
spawn passwd $USERNAME
expect {
# 遇到New password:输入密码并回车
"New password:" {send "$PASSWORD\r"; exp_continue}
# 遇到Retype new password再次输入密码时,自动输入密码并回车
"Retype new password" {send "$PASSWORD\r"}
}
expect eof
EOF
例子2:
#!/usr/bin/expect -f
# 需求:将脚本发送到远程服务器并执行的操作
set serverIp [lindex $argv 0]
set password [lindex $argv 1]
set file_name [lindex $argv 2]
set local_path [lindex $argv 3]
set remote_path [lindex $argv 4]
# 发送脚本到远程服务器
set timeout 15
send "scp -r $local_path/$file_name $serverIp:$remote_path\r"
expect {
"password:" {send "$password\r"; exp_continue}
"(yes/no)?" {send "yes\r"; exp_continue}
}
expect "#"
expect eof
# 登陆远程服务器
set timeout 10
spawn ssh [lindex $serverIp]expect {
"password:" {send "$password\r"; exp_continue}
"(yes/no)?" {send "yes\r"; exp_continue}
}
expect "#"
# 切换到具体目录并执行脚本
send "cd $remote_path\r"
expect "#"
set timeout 60
send "./$file_name\r"
expect "#"
expect eof
设置集群机器间免密登陆
# 其中一台绵密登陆其他机器的设置, 需要都能互相免密for循环每台机都执行一遍即可
server_name="admin"
server_password="123456"
nodes=("192.168.0.0" "192.168.0.2" "192.168.0.3")
if [ ! -f ~/.ssh/id_rsa ];then
ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsaelse
echo "id_rsa hs created ..."
fi
for (( i=0;i<${#nodes[@]}; i++ )); do
server_ip=${nodes[$i]}
echo "ssh-copy-id $server_name@$server_ip"
expect << EOF
set timeout 30
spawn ssh-copy-id $server_name@$server_ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$server_password\n" }
}
expect "#"
expect eof
EOF
done
vim 全局替换字符串
# 将tomcat替换成jetty的例子(在底行模式执行)
%s/tomcat/jetty