shell脚本总结
前言
总结了工作中遇到的一些shell使用情况,不定期更新,留作后续参考。
总结
- shell函数以及传参
#/bin/bash
# 函数形式
add(){
# 参数 1
para1=$1
# 参数 2
para2=$2
# 参数处理
sum=`echo "$para1 $para2"|awk '{printf("%d",$1+$2)}'`
echo $sum
# 返回,注意,只能是整数0~255
return 0
}
# 调用函数 add
add 1 2
# 打印执行结果(即为return 的返回值)
echo $?
# 想要得到函数处理结果,尤其是需要获取字符串时,可以使用此方式
a=$(add 1 2)
echo $a
return:“假的”返回; echo:“真的”返回
- 数组
array=(1 2 3 "a" b c)
for i in ${array[*]}
do
echo $i
done
- case
input=1
case $input in
1)
echo "one"
;;
2)
echo "two"
;;
3|4|5|6)
echo "$input"
;;
*)
echo "not find"
;;
esac
- if
# [[]]中间的条件需要和左右括号各间隔一个空格
if [[ 条件1 ]]; then
elif [[ 条件2 ]]; then
else
fi
- 调用linux指令,并捕获返回值
a=`ls`
a=`cat 1.txt`
a=$(ls)
- 字符串处理
a="1/2/3.txt"
# 删除掉最后一个 / 及 / 左边的字符串,得到 3.txt
b=${a##*/}
# 删除最后一个 / 及 / 右边的字符串,得到 1/2
c=${a%/*}
# 删除最后一个 . 及 . 右边的字符串,得到 3
d=${b%.*}
# 从第4位开始截取a, 得到/3.txt
echo ${a:3}
# 获取字符串a的长度
echo ${#a}
# 大写转小写
tst="THIS IS A TEST"
tst2=`echo "$tst" | awk '{print tolower($0)}'`
# 小写转大写
tst3=`echo "$tst2"| awk '{print toupper($0)}'`
参考博客https://www.cnblogs.com/yutingliuyl/p/7236501.html
- 询问
a=1
if [[ a==1 ]]; then
echo -e "\n"
# 打印红色提示
printf "\033[0;31mWarning: a=$a\033[0m";
echo -e "\n"
# 询问是否继续
read -r -p "Are you sure to be continue? [Y/n] " input
case $input in
[yY][eE][sS]|[yY])
echo "ok, let's continue"
echo "-----------------------------------------"
;;
[nN][oO]|[nN])
exit 0
;;
*)
echo "Invalid input..."
exit 1
;;
esac
fi
- 运算符
-e file/dir 判断文件或文件夹是否存在,如果是,返回true
$a -eq $b 判断a是否等于b,等于则返回true
$a -ne $b 判断a是否不等于b,等于则返回false
$a -gt $b 判断a是否大于b,如果是,返回true
$a -lt $b 判断a是否小于b,如果是,返回false
$a -ge $b 判断a是否大于等于b,如果是,返回true
$a -le $b 判断a是否小于等于b,如果是,返回true
- 多行注释
:<<EOF
这是注释
EOF
多行注释还有其它形式,具体可以参考菜鸟教程
- 传递参数
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数。如"$*"用__"__括起来,以"$1 $2 ... $n"的形式输出所有参数
$$ 脚本运行的当前ID号
$! 后台运行的最后一个进程的ID号
#@ 与__$*__相同,但是使用时加引号,并在引号中返回每个参数。如"#@"用__""__括起来,以"$1" "$2" ... "$n" 的形式输出所有参数
$- 显示Shell使用的当前选项,与__set__命令功能相同
$? 显示最后命令的退出状态。0表示没有错误,其它任何值表示有错误。
8,9,10参考菜鸟教程https://www.runoob.com/linux/linux-shell.html
- 根据端口号查看进程命令
get_pidname_by_port.sh [PORT]
#!/bin/bash
function Usage(){
echo "Usage:"
echo "$0 [PORT]"
exit 0
}
function getCmdByPid(){
pid=$1
cmd=`ps -p $pid -o command=`
dir=`ls -la /proc/${pid}/ |grep cwd|awk -F' ' '{print $11}'`
echo $cmd "dir:"$dir
}
PORT=$1
if [[ $PORT == "" ]];then
Usage
fi
pids=`lsof -i:$PORT|grep -v PID|awk -F' ' '{print $2}'|xargs`
if [[ $pids != '' ]];then
echo "PORT PID COMMAND DIR"
fi
for s in $pids
do
cmdStr=$(getCmdByPid $s)
echo $PORT $s $cmdStr
done
- grep
- grep -v 不显示的内容,比如ps -ef|grep -v grep就会在进程中过滤调grep命令本身
- grep -E "内容1|内容2" 扩展正则表达式,返回包含内容1或内容2的行
- 自定义日志管理
- 格式化输出 时间:信息
- 日志文件大小管理:超过100M自动清空
log.sh
#!/bin/bash
# 日志输出
logPath=my.log
logMaxSize=$(echo "100 1024 1024"|awk '{printf("%d",$1*$2*$3)}')
function log()
{
msg=$1
# 日志大小超过最大,清空日志
if [[ -e $logPath ]];then
logSize=$(ls -l $logPath|awk '{print $5}')
if [[ $logSize -gt $logMaxSize ]];then
echo -n "" > $logPath
fi
fi
date=$(date "+%Y-%m-%d %H:%M:%S")
logStr=$date": "$msg
echo $logStr
echo $logStr >> $logPath
}
log "hello"
chmod +x log.sh && ./log.sh
# 2023-03-25 16:55:49: hello
- 启停 python http.server 文件服务
start.sh
#!/bin/bash
port=12123
log=out.log
pids=`ps -ef|grep "python3 -m http.server -b 0.0.0.0 ${port}"|grep -v grep|awk -F ' ' '{ print $2}'|xargs`
if [[ ${pids} != "" ]];then
kill -9 ${pids}
echo "${pids} have been killed"
fi
nohup python3 -m http.server -b 0.0.0.0 ${port} 2>&1 >> ${log} &
echo "http file server started: http://0.0.0.0:${port}"
kill.sh
#!/bin/bash
port=12123
log=out.log
pids=`ps -ef|grep "python3 -m http.server -b 0.0.0.0 ${port}"|grep -v grep|awk -F ' ' '{ print $2}'|xargs`
if [[ ${pids} != "" ]];then
kill -9 ${pids}
echo "${pids} have been killed"
fi
- 设置文件/文件夹被占用
有时为了方便测试或其他要求,需要将文件/文件夹设置为被占用,脚本使用chattr实现
#!/bin/bash
# 设置一个文件/文件夹是否被占用
path=$1
action=$2
function Usage()
{
echo -e "Usage:${0} [file_path] [f/uf]"
echo -e "file_abs_path: file path"
echo -e "f/uf: f-fixed, uf-unfixed"
exit 0
}
if [[ ${path} == "" || ${action} == "" ]];then
Usage
fi
if [[ -e ${path} ]];then
echo -e "check file exists success"
else
echo -e "Error: ${path} not exists"
Usage
fi
echo -e "start get file org status:"
lsattr -d ${path}
file_status=`lsattr -d ${path}|grep "i"|wc -l`
if [[ ${file_status} > 0 ]];then
echo -e "${path} is fixed"
else
echo -e "${path} is unfixed"
fi
echo -e ""
echo -e "******"
if [[ ${action} == "f" ]];then
echo -e "start set ${path} fixed"
chattr +i ${path}
lsattr -d ${path}
echo -e "******"
echo -e "set ${path} fixed finished"
elif [[ ${action} == "uf" ]];then
echo -e "start set ${path} unfixed"
chattr -i ${path}
lsattr -d ${path}
echo -e "******"
echo -e "set ${path} unfixed finished"
else
echo -e "Error: ${action} not in (f, uf)"
Usage
fi
- 关机前可以手动执行的脚本
关机前手动执行脚本,可以手动配置成service,目前做到的是kill所有想停止的任务,停止所有的podman容器
handle_bf_shutdown.sh
#!/bin/bash
function kill_process()
{
key_name=$1
if [[ ${key_name} == "" ]];then
echo -e "-- kill_process: key_name is None"
return
fi
echo -e "-- start kill ${key_name}"
pids=`ps -ef|grep ${key_name}|grep -v grep|awk -F ' ' '{print $2}'|xargs`
if [[ ${pids} != "" ]];then
echo -e "-- find pid:${pids}, start kill"
kill -9 ${pids}
fi
}
function kill_all_needed_process()
{
echo -e "### start kill all process needed"
# 此处可以扩展任何想kill掉的任务关键词,注意用空格隔开不要用逗号,如
# keys=("task1" "task2")
keys=("handle_old_data")
for item in "${keys[@]}"
do
kill_process ${item}
done
}
function stop_all_container()
{
echo -e "### start stop all container"
podman ps -a --format={{.Names}} | while read container_name
do
echo -e "start stop ${container_name}"
podman stop ${container_name}
done
}
kill_all_needed_process
stop_all_container
- tcpdump 抓post的包
sudo tcpdump -i any -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0:1] & 0xf) << 2)) - ((tcp[12:1] & 0xf0) >> 2)) > 0) and (tcp[13] & 0x18) = 0x18)'
解释:
-i any:监听所有接口。
-A:以 ASCII 形式打印出数据包的内容。
-s 0:抓取整个包(默认情况下,tcpdump 只捕获前 68 字节)。
tcp port 80:过滤 TCP 端口 80。
(((ip[2:2] - ((ip[0:1] & 0xf) << 2)) - ((tcp[12:1] & 0xf0) >> 2)) > 0):确保投递的是有负载的数据包。
(tcp[13] & 0x18) = 0x18:过滤出带有 PSH 和 ACK 标志的数据包,通常表示一个中等大小的数据块。
分类:
Linux以及服务器开发
, shell
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App