ash执行kill提示需指定杀除对象 读取/dev/rs232发MQTT时cat进程无法终止
问题根源
- 你用到的命令替换
$()会等待内部命令执行完成后才返回输出结果,哪怕你在内部将cat放到后台运行,命令替换仍会阻塞等待cat进程退出,之后才会执行后续的pid=$!逻辑。此时要么cat进程已经退出、要么进程仍在阻塞读设备,$!根本无法捕获到本次cat进程的PID,导致kill的参数为空,触发ash: you need to specify whom to kill报错。 /dev/rs232是串口字符设备,cat默认会持续读取设备内容直到收到EOF,只要设备没有主动断开,cat进程永远不会主动退出。
可行解决方案
方案1:使用timeout命令(推荐,大部分带BusyBox的嵌入式环境都支持)
直接用timeout限制cat的运行时长,读完现有串口内容后自动终止进程,无需手动管理PID:
#!/bin/ash while true; do # 0.1秒超时可根据串口波特率调整,保证读完所有缓存内容即可 rs=$(timeout 0.1 cat /dev/rs232) # 非空内容才推送MQTT,避免发送无效空消息 if [ -n "$rs" ]; then mosquitto_pub -h 替换为实际MQTT服务IP -m "$rs" -t rs_test/message fi # 加小延迟避免循环占满CPU sleep 0.2 done
方案2:无timeout时用临时文件中转
如果系统没有内置timeout命令,可以用临时文件存输出,后台运行cat后延迟手动杀进程:
#!/bin/ash # 提前创建临时文件,避免每次循环重复生成 touch /tmp/rs232_buffer while true; do cat /dev/rs232 > /tmp/rs232_buffer & pid=$! # 等待cat读完现有缓存内容 sleep 0.1 # 杀进程时丢弃错误输出,避免进程已经退出时的报错 kill $pid 2>/dev/null rs=$(cat /tmp/rs232_buffer) # 清空缓存文件避免下次读取重复内容 > /tmp/rs232_buffer if [ -n "$rs" ]; then mosquitto_pub -h 替换为实际MQTT服务IP -m "$rs" -t rs_test/message fi sleep 0.2 done
方案3:单条串口输出场景用read轻量实现
如果你的串口每次输出都是单行内容,可以直接用ash内置的read命令,无需创建额外进程:
#!/bin/ash while true; do # -t参数指定读取超时时间,读到内容就返回 if read -t 0.1 rs < /dev/rs232; then mosquitto_pub -h 替换为实际MQTT服务IP -m "$rs" -t rs_test/message fi sleep 0.1 done
额外说明
不要使用kill $(pgrep cat)的逻辑,会误杀系统中其他正常运行的cat进程,且无cat进程时仍会触发kill参数为空的报错。
内容的提问来源于stack exchange,提问作者user14490575
相关产品推荐
相关产品推荐

