incron触发Mycroft列表导出bash脚本仅执行首条cp命令故障求助
我的目标是将Mycroft技能"List-Manager"中的所有列表导出为格式化拆分的txt文件,传输到我的Nextcloud-Notes-Skill。谷歌助手和Alexa是更简便的方案,但我不想使用这类服务。
我编写的bash脚本在终端中可正常完成列表格式化和拆分工作。
Mycroft技能使用的文本文件内容如下:{"Remind me": ["remind_item_1", "remind_item_2"], "shopping": ["mate", "book", "keyboard", "bavarian beer"]}
导出后会生成两个文本文件
第一个文件名为:Remind me
- remind_item_1
- remind_item_2
第二个文件名为:shopping
- mate
- book
- keyboard
- bavarian beer
在展示代码前先说明几点:首先我认为存在更优的实现方案,我是自学的非专业开发人员,刚接触bash脚本编写,希望使用系统自带资源实现功能并学习相关知识。
我使用incron监控文件变更,每次修改列表时incron都会触发脚本执行,规则配置如下:
/opt/mycroft/skills/list-manager.lb803/data.json IN_MODIFY /bin/bash /home/pi/my_directory/notes_skill.sh
incron运行正常,可触发下方脚本但仅能执行第一条copy命令,每次都能在目录中生成data_list_manager.txt文件,但后续命令无任何执行痕迹。incron已配置pi和root用户的执行权限,所有文件都具备pi或root权限,脚本在终端手动执行可正常运行,仅通过incron触发时会在执行完cp命令后停止,暂未找到故障原因。
当前版本代码仅支持导出2个列表,待问题解决后我会优化适配更多列表。我在echo、sed等命令前添加了/bin/绝对路径,是因为查阅资料得知incron运行环境和终端不同,需要指定命令的完整路径。
#!/bin/bashcp cp /opt/mycroft/skills/list-manager.lb803/data.json /home/pi/my_directory/data_list_manager.txt #wait foo="$(/bin/cat /home/pi/my_directory/data_list_manager.txt | /bin/sed s/[[{}"]//g)" foo="$(/bin/echo "$foo" | /bin/sed -e s/,[[:space:]]/@@/g -e s/:[[:space:]]/@@@@/g -e s/[]]/@@@@/g)" foo="$(/bin/echo "$foo" | /bin/sed -e s/@@@@@@/\n/g -e s/@@@@/\n@@@/g)" /bin/echo "$foo" >/home/pi/my_directory/splitfile.txt /usr/bin/split -l2 /home/pi/my_directory/splitfile.txt #wait nam="$(/bin/cat /home/pi/my_directory/xaa | /bin/sed q)" foo="$(/bin/cat /home/pi/my_directory/xaa | /bin/sed '2!d')" foo="$(/bin/echo "$foo" | /bin/sed -e s/@@@/\-\ [\ ]\ /g -e s/@@/\n\-\ [\ ]\ /g)" /bin/echo "$foo" >/home/pi/my_directory/Listen/"$nam".txt nam="$(/bin/cat /home/pi/my_directory/xab | /bin/sed q)" foo="$(/bin/cat /home/pi/my_directory/xab | /bin/sed '2!d')" foo="$(/bin/echo "$foo" | sed -e s/@@@/\-\ [\ ]\ /g -e s/@@/\n\-\ [\ ]\ /g)" /bin/echo "$foo" >/home/pi/my_directory/Listen/"$nam".txt nam="$(/bin/cat /home/pi/my_directory/xac | /bin/sed q)" foo="$(/bin/cat /home/pi/my_directory/xac | /bin/sed '2!d')" foo="$(/bin/echo "$foo" | /bin/sed -e s/@@@/\-\ [\ ]\ /g -e s/@@/\n\-\ [\ ]\ /g)" /bin/echo "$foo" >/home/pi/my_directory/Listen/"$nam".txt nam="$(/bin/cat /home/pi/my_directory/xad | /bin/sed q)" foo="$(/bin/cat /home/pi/my_directory/xad | /bin/sed '2!d')" foo="$(/bin/echo "$foo" | /bin/sed -e s/@@@/\-\ [\ ]\ /g -e s/@@/\n\-\ [\ ]\ /g)" /bin/echo "$foo" >/home/pi/my_directory/Listen/"$nam".txt
- 修正脚本首行的笔误,把
#!/bin/bashcp改成#!/bin/bash,手动执行时你是直接指定bash运行脚本,不会触发shebang解析错误,但incron执行时会识别到错误的解释器路径直接终止运行。 - incron没有继承终端的工作目录配置,split命令生成的xaa/xab等文件默认会写入到系统根目录或者root目录,后续读取
/home/pi/my_directory/xaa时找不到文件直接报错。可以在cp命令前加一行cd /home/pi/my_directory || exit 1强制切换工作目录,或者把split命令修改为/usr/bin/split -l2 /home/pi/my_directory/splitfile.txt /home/pi/my_directory/x指定输出路径前缀。 - 修正一处未写绝对路径的sed命令,处理xab的那行
sed -e s/@@@/改成/bin/sed -e s/@@@/,避免incron环境找不到命令。 - 可选:在脚本开头加一行
exec > /tmp/notes_skill.log 2>&1,所有运行输出和报错都会写入该日志文件,后续出现问题可以直接查日志定位。
内容的提问来源于stack exchange,提问作者subduck

