shell 脚本技巧 ,健壮性
ssh 远程运行命令
pssh
https://blog.csdn.net/fdipzone/article/details/23000201
#!/bin/bash
ssh -f -n -l www-online 192.168.110.34 “/home/www-online/uptimelog.sh &” # 后台运行ssh
pid=$(ps aux | grep “ssh -f -n -l www-online 192.168.110.34 /home/www-online/uptimelog.sh” | awk ‘{print $2}’ | sort -n | head -n 1) # 获取进程号
echo “ssh command is running, pid:${pid}”
sleep 3 && kill ${pid} && echo “ssh command is complete” # 延迟3秒后执行kill命令,关闭ssh进程,延迟时间可以根据调用的命令不同调整
exit 0
————————————————
版权声明:本文为CSDN博主「傲雪星枫」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fdipzone/article/details/23000201
getopts 与 getopt ,shell 脚本 接收 外界参数
https://cloud.tencent.com/developer/article/1043821
awk 获取变量
work_pwd="/cloud/app/sls-common/WebServer#/sls_web/1207787_sls-common_WebServer"
## 基础样式
sudo cat > ./overwrite.sh << EOF
#!/bin/sh
work_dir=/cloud/app/sls-backend-server/InitDependentSystem#/init_dependent_system
ls \$work_dir/1350852_sls-backend-server_InitDependentSystem
sudo mkdir \$work_dir/1350852_sls-backend-server_InitDependentSystem.overwrite
sudo /cloud/tool/tianji/overwrite add sls-backend-server InitDependentSystem# init_dependent_system 1350852_sls-backend-server_InitDependentSystem 30 -f ## 添加 overwrite
sudo cp -pr \$work_dir/1350852_sls-backend-server_InitDependentSystem/* \$work_dir/1350852_sls-backend-server_InitDependentSystem.overwrite/
# sudo /cloud/tool/tianji/overwrite remove sls-backend-server InitDependentSystem# init_dependent_system 1350852_sls-backend-server_InitDependentSystem ## 移除 overwrite
# sudo rm -rf /cloud/app/sls-backend-server/InitDependentSystem#/init_dependent_system/1350852_sls-backend-server_InitDependentSystem.overwrite
sudo tjc stop sls-backend-server.InitDependentSystem#
sudo tjc start sls-backend-server.InitDependentSystem#
EOF
## 修改参数
eval $(echo $work_pwd|awk -F"/cloud/app" '{print $2}'|awk -F"/" '{printf("Service=%s;SR=%s;APP=%s;BuildID=%s;",$2,$3,$4,$5)}')
sudo sed -i "s/1350852_sls-backend-server_InitDependentSystem/$BuildID/g" ./overwrite.sh # 修改 buildID
sudo sed -i "s/sls-backend-server/$Service/g" ./overwrite.sh # 修改 service
sudo sed -i "s/InitDependentSystem#/$SR/g" ./overwrite.sh # 修改 SR
sudo sed -i "s/init_dependent_system/$APP/g" ./overwrite.sh # 修改 application
shell 脚本技巧 ,健壮性
https://zhuanlan.zhihu.com/p/73728157
https://twosee.cn/2018/03/18/stronger-shell/#%E4%BD%BF%E7%94%A8set-u
https://segmentfault.com/a/1190000006900083
https://segmentfault.com/a/1190000002539169
https://zhuanlan.zhihu.com/p/46100771
https://stackoverflow.com/questions/35800082/how-to-trap-err-when-using-set-e-in-bash
例子
#!/bin/bash
set -e -o errtrace -o pipefail ## set -eE / set -e -o errtrace 检测到 程序出错后,报错,中断。
err() {
echo "Error occurred:"
awk 'NR>L-3 && NR<L+3 { printf "%-5d%3s%s\n",NR,(NR==L?">>>":""),$0 }' L=$1 $0
}
## 用来捕获 异常的 信号, ,捕获到之后, 执行上面的 err() {} 函数
trap 'err $LINENO' ERR
## 用来捕获异常的 函数。
function error_exit {
echo "$1" 1>&2
exit 1
}
ARGS=`getopt -o h:: --long "src_files:,dest_dir:,remove::" -n 'example.sh' -- "$@"`
if [ $? != 0 ]; then
## echo -e '\n' 换行
echo -e "EROOR, the ADD overwrite option is: bash overwrite.sh --src_files=XXX --dest_dir=XX \n or the REMOVE overwrite option is: bash overwrite.sh --dest_dir=XX --remove"
exit 1
fi
#echo $ARGS , getopt, 还有一种 getopts
#将规范化后的命令行参数分配至位置参数($1,$2,...)
eval set -- "${ARGS}"
while true
do
case "$1" in
-h)
echo -e "the ADD overwrite option is: bash overwrite.sh --src_files=XXX --dest_dir=XX \n or the REMOVE overwrite option is: bash overwrite.sh --dest_dir=XX --remove"
echo "--src_files is divided by ','"
echo "--dest_dir is like '/cloud/app/sls-common/WebServer#/sls_web/current', it must start with '/cloud/app/sls-common/WebServer#/sls_web/' "
echo "--remove ,when you want to remove overwrite"
shift
;;
--src_files)
echo "--src_files is $2";
source_files_str=`echo $2 |sed 's/,/ /g'`; ## 将 逗号 转为空格
read -a source_files_list <<< $source_files_str; ## 将 str 转为数组, 以 单个或多个 空格为分隔。
for source_file in ${source_files_list[*]}
do
## “||” error_exit 捕获异常, “||”之前的的语句 执行失败,就会 执行 后面的。
[[ -e $source_file ]] || error_exit "$source_file no exist"
done
shift 2
;;
--dest_dir)
echo $2 | grep ^/cloud/app/ > /dev/null 2>&1 || error_exit "--dest_dir must start with '/cloud/app/'"
echo "--dest_dir is $2"
dest_dir=$2
shift 2
;;
--remove)
echo "remove overwrite"
scripts_option="remove"
shift 2
;;
--)
shift
break
;;
*)
echo -e "EROOR, the ADD overwrite option is: bash overwrite.sh --src_files=XXX --dest_dir=XX \n or the REMOVE overwrite option is: bash overwrite.sh --dest_dir=XX --remove"
echo "Internal error!"
exit 1
;;
esac
done
#处理剩余的参数
for arg in $@
do
echo "processing $arg"
done
write_overwrite_sh () {
## \$current_dir 在 cat 添加的时候 转义。
sudo cat > ./overwrite.sh << EOF
#!/bin/sh
current_dir=/cloud/app/sls-backend-server/InitDependentSystem#/init_dependent_system
sudo mkdir -p \$current_dir/1350852_sls-backend-server_InitDependentSystem.overwrite
sudo /cloud/tool/tianji/overwrite add sls-backend-server InitDependentSystem# init_dependent_system 1350852_sls-backend-server_InitDependentSystem 30 -f
sudo cp -pr \$current_dir/1350852_sls-backend-server_InitDependentSystem/* \$current_dir/1350852_sls-backend-server_InitDependentSystem.overwrite/
##### sudo /cloud/tool/tianji/overwrite remove sls-backend-server InitDependentSystem# init_dependent_system 1350852_sls-backend-server_InitDependentSystem
##### sudo rm -rf /cloud/app/sls-backend-server/InitDependentSystem#/init_dependent_system/1350852_sls-backend-server_InitDependentSystem.overwrite
# echo '### restart SR '
sudo tjc stop sls-backend-server.InitDependentSystem# > /dev/null 2>&1 && sudo tjc start sls-backend-server.InitDependentSystem# > /dev/null 2>&1;
EOF
}
get_common_varabiles () {
## 获取变量 ## 按'/' 分隔后 设置变量。 Service=$2 ;SR=$3 ;APP=$4;
eval $(echo $dest_dir|awk -F"/cloud/app" '{print $2}'|awk -F"/" '{printf("Service=%s;SR=%s;APP=%s;",$2,$3,$4)}')
current_dir=`echo $dest_dir|awk -F'current' '{print $1}'`
alread_install_dir=$current_dir'current/alread_installed'
overwrite_script=$current_dir'overwrite.sh'
machine_ip_str=`tj_show -ip -r $Service'.'$SR`
read -a machine_ip_list <<< $machine_ip_str
echo `ssh -l root ${machine_ip_list[0]} ls -l $current_dir` > BuildID_str
BuildID=`cat BuildID_str|grep current|awk -F'-> ' '{print $2}'|awk '{print $1}'|sed 's/.overwrite//g'`
echo "### buildID:",$BuildID
}
fix_overwrite_sh () {
chmod +x ./overwrite.sh
sudo sed -i "s/1350852_sls-backend-server_InitDependentSystem/$BuildID/g" ./overwrite.sh
sudo sed -i "s/sls-backend-server/$Service/g" ./overwrite.sh
sudo sed -i "s/InitDependentSystem#/$SR/g" ./overwrite.sh
sudo sed -i "s/init_dependent_system/$APP/g" ./overwrite.sh
}
get_remote_varabiles () {
restart_SR_cmd=`tail -n 1 overwrite.sh`
remove_overwrite_cmd=`tail -n 5 overwrite.sh|head -n 1|awk -F'##### ' '{print $2}'`
re_overwrite_dir=`tail -n 4 overwrite.sh|head -n 1|awk -F'##### ' '{print $2}'`
}
build_overwrite () {
## 用 `` 是为了让 保证 先让这个 shell 命令执行完,才执行下一条 shell 命令。
scp_done=`scp ./overwrite.sh root@$machine_ip:/$current_dir > /dev/null 2>&1 &`
echo `ssh -l root $machine_ip $overwrite_script`
## for 遍历
for source_file in ${source_files_list[*]}
do
echo '## ip: '$machine_ip' '$source_file >> source_file.txt
scp_done=`scp $source_file root@$machine_ip:/$dest_dir > /dev/null 2>&1 &`
done
echo `ssh -l root $machine_ip rm -rf $current_dir'current/alread_installed'`
echo `ssh -l root $machine_ip $restart_SR_cmd`
}
remove_overwrite () {
echo `ssh -l root $machine_ip "$remove_overwrite_cmd > /dev/null 2>&1 &"`
echo `ssh -l root $machine_ip "$re_overwrite_dir > /dev/null 2>&1 &"`
}
main () {
echo "## source" > source_file.txt
echo "## machine_ip" > machine_ip.txt
for machine_ip in ${machine_ip_list[*]}
do
echo $machine_ip >> machine_ip.txt
if [ $scripts_option ]
then
remove_overwrite
echo "### Remove overwrite, ip:$machine_ip $remove_overwrite_cmd "
elif [ $dest_dir ] && [ $source_files_list ]
then
build_overwrite
echo "### build ip="$machine_ip,' '$Service/$SR/$APP/$BuildID/'successfully!'
fi
done
}
write_overwrite_sh
get_common_varabiles
fix_overwrite_sh
get_remote_varabiles
main