function thread_func() {
# 调用哪个函数执行多线程
executed_func=$1
[[ -z ${executed_func} ]] && error_exit "调用的函数为空"
# 传入进来要循环的文件
list_file=${2}
[[ ! -s ${list_file} ]] && error_exit "列表文件为空或者文件不存在: ${list_file}"
# 设置并发的线程数,根据本服务器的CPU核数是最合适的
CPU_count=$(cat /proc/cpuinfo| grep "processor" | wc -l)
let thread=${CPU_count}*2-2 # 减2是因为给服务器留点余地
[[ ${thread} -lt 2 ]] && thread=2
[[ ${thread} -gt 15 ]] && thread=15 # # 根据自己的情况设置峰值
tempfifo="my_temp_fifo"
mkfifo ${tempfifo} # 创建文件描述符文件
# 使文件描述符为非阻塞式
exec 6<>${tempfifo} # 创建文件描述符,以可读(<)可写(>)的方式关联管道文件,这时候文件描述符3就有了有名管道文件的所有特性
rm -f ${tempfifo} # 关联后的文件描述符拥有管道文件的所有特性,所以这时候管道文件可以删除,我们留下文件述符来用就可以了
# 为文件描述符创建占位信息
for ((Multithreading=1;Multithreading<=${thread};Multithreading++))
do {
echo -ne "\n" 1>&6
}
done >&6
# 读取参数列表文件
exec 5<${list_file}
while read LINE <&5
do
{
read -u6 # 代表从管道中读取一个令牌
{
${executed_func} "${LINE}"
echo -ne "\n" 1>&6 # 代表执行到最后,读取下一个管道中一个令牌
} &
}
done
wait # 等待所有任务执行完退出线程任务
# 关闭fd6管道
exec 6>&- #关闭文件描述符的写
exec 6<&- #关闭文件描述符的读
}
function ls_server() {
IP=$1
${SSH} 22 ${IP} 'ls /root/'
[[ $? -ne 0 ]] && echo "服务器(${IP})ls失败" > logs/error.log && return 1
}
function rm_server() {
IP=$1
${SSH} 22 ${IP} 'rm /root/test.txt'
[[ $? -ne 0 ]] && echo "服务器(${IP})rm失败" > logs/error.log && return 1
}
thread_func ls_server tmp/ip_list.txt
grep '失败' logs/error.log
[[ $? -eq 0 ]] && exit 1
thread_func rm_server tmp/ip_list.txt
grep '失败' logs/error.log
[[ $? -eq 0 ]] && exit 1
shell脚本多线程
于 2022-06-30 10:05:34 首次发布