使用shell并发执行系统命令

一 解决方案

旧方案为挨个执行shell_exec,串行执行,虽然执行很快,奈何监听命令众多,redis连接有等待时间等,有的还需要执行多次取平均值,所以执行完已超过1min

故,改为并发执行命令,单个命令加timeout,则永远可以在10s左右执行完!

  • golang形式,需要在该php-server上安装go环境,虽然简单,但生产环境尽量不乱动配置
  • php-swoole形式,同上,一个shell文件而已,没必要挨个server都装拓展
  • shell的循环&形式,循环体内正则匹配因为本人不熟悉,直接丢给php文件来处理

二 linux.sh

timest=$(date "+%Y-%m-%d %H:%M:%S")
echo "start: "$timest

SERVER=manager-admin
DEBUG=0
while getopts ":s:d:" opt
do
	case $opt in
		s)
			SERVER="$OPTARG"
		;;
		d)
			DEBUG="$OPTARG"
		;;
	esac
done

mkfifo /home/log/crontab/linux_status
exec 0316<>/home/log/crontab/linux_status
rm -rf /home/log/crontab/linux_status
for ((n=1;n<=10;n++));do #10>cmd num ji ke
	echo >&0316
done

for ((i=1;i<=7;i++));do
	read -u0316
{
	if [ $i == 1 ]
	then
		#负载
		QDATA=$(timeout 10 sar -q 1 5)
		echo "$QDATA" >> "/home/log/crontab/linux_status_"$SERVER"_compelet_q.cron.log"
		process_tm=$(date "+%Y-%m-%d %H:%M:%S")
		echo "负载|end: "$process_tm
	elif [ $i == 2 ]
	then
		#CPU
		CPUDATA=$(timeout 10 sar -u 1 5)
		echo "$CPUDATA" >> "/home/log/crontab/linux_status_"$SERVER"_compelet_cpu.cron.log"
		process_tm=$(date "+%Y-%m-%d %H:%M:%S")
		echo "CPU|end: "$process_tm
	elif [ $i == 3 ]
	then
		#内存
		MEMDATA=$(timeout 10 sar -r 1 5)
		echo "$MEMDATA" >> "/home/log/crontab/linux_status_"$SERVER"_compelet_mem.cron.log"
		process_tm=$(date "+%Y-%m-%d %H:%M:%S")
		echo "内存|end: "$process_tm
	elif [ $i == 4 ]
	then
		#磁盘IO
		IODATA=$(timeout 10 sar -d 1 5)
		echo "$IODATA" >> "/home/log/crontab/linux_status_"$SERVER"_compelet_io.cron.log"
		process_tm=$(date "+%Y-%m-%d %H:%M:%S")
		echo "磁盘IO|end: "$process_tm
	elif [ $i == 5 ]
	then
		#磁盘空间
		DISKDATA=$(timeout 10 df -h)
		echo "$DISKDATA" >> "/home/log/crontab/linux_status_"$SERVER"_compelet_disk.cron.log"
		process_tm=$(date "+%Y-%m-%d %H:%M:%S")
		echo "磁盘空间|end: "$process_tm
	elif [ $i == 6 ]
	then
		#redis_h5
		if [ $SERVER == "manager-admin" ]; then
			php /home/sh/linux_status/linux_status_redis.php $SERVER h5
		fi
		process_tm=$(date "+%Y-%m-%d %H:%M:%S")
		echo "redis_h5|end: "$process_tm
	elif [ $i == 7 ]
	then
		#redis_admin
		if [ $SERVER == "manager-admin" ]; then
			php /home/sh/linux_status/linux_status_redis.php $SERVER admin
		fi
		process_tm=$(date "+%Y-%m-%d %H:%M:%S")
		echo "redis_admin|end: "$process_tm
	else
		echo "not known"$i
	fi

	echo >&0316
}&
done
wait
# echo "linux_status_compelet"
exec 0316<&-
exec 0316>&-
timemid=$(date "+%Y-%m-%d %H:%M:%S")
echo "mid: "$timemid
php /home/sh/linux_status/linux_status.php $SERVER $DEBUG
timeend=$(date "+%Y-%m-%d %H:%M:%S")
echo "end: "$timeend

  

三 linux_status_redis.php、linux_status.php

分别为redis连接命令和对并发进程输出文件进行正则匹配,此处略

四 说明

  • shell各个进程通信我暂时通过文本,效率低下,因为并发不大暂时未改进
  • getopts获取调用脚本的参数-s servername -d 是否debug模式
  • mkfifo filepath 创建命名管道,exec 0316<>/home/log/crontab/linux_status创建文件描述符并关联到管道文件
  • echo >&0316 read -u0316 类似于golang、swoole的阻塞管道,做并发协程数控制的
  • 循环体&为丢到子进程执行,wait等待所有子进程执行完毕,不wait则可能子进程未执行完而父进程直接end了
  • exec 0316<&- 关闭文件描述符的写,exec 0316>&- 关闭读

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你可以使用以下几种方法在 shell 脚本中并发执行命令: 1. 使用 & 符号:在命令后面加上 &,表示在后台运行该命令。 例如: ``` command1 & command2 & ``` 2. 使用 nohup 命令:nohup 命令可以在后台运行命令,并且不会因为终端关闭而停止运行。 例如: ``` nohup command1 & nohup command2 & ``` 3. 使用 xargs 命令:xargs 命令可以将输入的一个或多个命令并行执行。 例如: ``` echo "command1 command2" | xargs -P 2 -I {} sh -c {} & ``` 4. 使用 parallel 命令:parallel 命令是一个专门用于并行执行命令的工具。 例如: ``` parallel -j 2 command1 command2 ``` 这些方法都可以帮助你在 shell 脚本中并发执行命令,你可以根据自己的需求选择合适的方法。 ### 回答2: Shell脚本可以使用多种方法实现并发执行命令,其中比较常见的方法有以下几种: 1. '&' 在Shell脚本中,可以使用'&'符号将命令放到后台执行,从而实现并发执行。例如: ``` command1 & command2 & ``` 2. 'wait' 使用'wait'命令可以等待所有后台任务执行完毕,然后继续执行下面的命令,例如: ``` command1 & command2 & wait echo "All tasks have finished." ``` 3. 'xargs' 使用'xargs'命令可以实现并发执行命令。'xargs'命令可以从标准输入或者文件中读取参数,并将这些参数传递给后面跟随的命令执行。例如,在Linux系统中可以使用'find'命令查找某个目录下的所有文件,并使用'xargs'命令并发执行'file'命令: ``` find /path/to/directory/ -type f | xargs -P 5 -I {} file {} ``` 'P'选项指定并发的进程数量。上面的例子中,设置并发进程的数量为5,'{}'表示使用每个文件名作为参数。上面的命令使用5个并发进程执行'file'命令。在这个例子中,每个进程会读取'find'命令输出的一部分文件列表并执行'file'命令。 4. 'parallel' 使用'parallel'命令可以方便地实现并发执行命令。'parallel'命令可以从标准输入或者文件中读取参数,并将这些参数传递给后面跟随的命令执行。例如,在Linux系统中可以使用'find'命令查找某个目录下的所有文件,并使用'parallel'命令并发执行'file'命令: ``` find /path/to/directory/ -type f | parallel file {} ``` '{}'表示使用每个文件名作为参数。上面的命令使用默认的最大并发执行'file'命令。 总的来说,以上几种方法都可以实现Shell脚本中的并发执行命令。需要注意的是,并发执行命令可能会导致资源竞争和错误的结果,因此在并发执行命令的时候需要仔细测试和调试,确保程序的正确性和可靠性。 ### 回答3: Shell脚本并发执行命令,通常需要使用多线程技术。多线程指的是同时执行多个线程,每个线程独立地执行一些任务。在Shell脚本中,可以通过使用Fork、Exec、Waitpid等系统调用来创建新的进程并执行命令,从而实现并发执行任务的目的。 在实际的应用中,常使用的多线程框架包括POSIX线程和Java多线程。POSIX线程是一种标准化的线程技术,可以实现多个线程同时运行。Java多线程则是Java语言中内置的线程库,使用起来更加方便快捷。 同时,在Shell脚本中,还可以使用command &或者使用nohup命令来实现并发执行命令。command &表示将命令后台运行,nohup则可以使命令在后台运行并且不会受到用户退出终端的影响。 需要注意的是,在并发执行命令时,需要注意对共享资源的并发访问。为了避免竞争条件和死锁等问题,应使用线程同步机制,如锁和信号量等,来确保线程之间访问共享资源的安全性。 另外,对于一些需要并发执行的任务,可以考虑分割任务,将大任务拆分成多个小任务,再进行并发执行。这样可以提高执行效率,也可以减少并发访问共享资源的冲突。 总之,Shell脚本并发执行命令是一项比较复杂的任务,需要使用多线程技术、同步机制以及任务分割等方法来实现。同时,也需要根据不同场景选择适当的并发执行方法,以保证程序的正确性和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值