文章目录[隐藏]
作为一名习惯折腾手机的用户,我之前经常在充电时手动运行一款电池容量检测脚本。但频繁手动操作加时刻关注结果,这让我养成个坏习惯,也让我陷入了“电池焦虑”。为了摆脱这种状态,我萌生了一个想法:让脚本自动运行,把充完电之后满电容量、锁容容量等核心结果写入日志,平时不用刻意关注,想起时再查看即可。本以为只是简单的配置自动化脚本,却没想到卡在了“日志写入”这个关键环节,还牵扯出了SELinux安全策略的坑。下面就把整个问题排查与解决过程分享给大家,希望能帮到有类似需求的朋友。
一、问题初现:手动运行正常,Tasker自动运行却写不了日志
第一步我先对酷安找到的原始脚本做了简单修改,核心是添加了日志写入路径,将指定将最终结果输出到脚本同级的TXT文件中。手动在终端通过SU权限执行时,一切正常,日志能完整记录电池相关数据;但当我配置Tasker,通过Tasker以SU权限调用脚本时,脚本能正常执行(电池检测逻辑生效),但日志文件都没被创建。
这就很奇怪了:同样是SU权限,为什么手动和自动执行的结果会不一样?难道Tasker的SU权限和终端的SU权限有区别?带着这个疑问,我开始了debug排查。
二、问题定位:添加debug日志,揪出SELinux和当前目录的锅
既然表面看不到问题,那就让脚本“自己说话”。我在脚本开头添加了一段debug逻辑,输出执行上下文、当前目录、权限信息等关键数据,同时指定写入一个绝对路径的debug日志(避免路径问题干扰排查)。debug脚本如下:
#!/system/bin/sh
# 调试日志输出逻辑
echo "===== TaskerSU执行上下文 =====" >> /sdcard/scripts/battery_debug.log
echo "当前用户:$(whoami)" >> /sdcard/scripts/battery_debug.log
echo "当前目录:$(pwd)" >> /sdcard/scripts/battery_debug.log
echo "SELinux状态:$(getenforce)" >> /sdcard/scripts/battery_debug.log
echo "脚本权限:$(ls -l $0)" >> /sdcard/scripts/battery_debug.log
echo "==============================" >> /sdcard/scripts/battery_debug.log
# 原电池检测逻辑(保留)
# ... 此处省略原始脚本代码 ...
通过TaskerSU执行修改后的脚本,查看debug日志后,问题瞬间清晰了,核心是两个关键差异:
- 当前目录不一致:手动终端SU执行时,当前目录是脚本所在的
/sdcard/ROM/script/,相对路径./battery_log.txt有效;而Tasker的SU的默认工作目录是/(根目录),脚本里的“当前目录”实际指向根目录,而根目录没有写入权限。 - SELinux策略限制:debug日志显示SELinux状态为
Enforcing(强制模式),终端SU的执行上下文是u:r:shell:s0(宽松策略,允许写文件),但TaskerSU的执行上下文是u:r:app_xxx:s0(APP专属上下文),即便有Root权限,SELinux也会拦截写文件操作。 - 除此之外,脚本770权限的生效也有问题:终端SU以
root:shell组执行,能匹配770权限(所有者·加同组可写);但Tasker的SU以root:app_xxx组执行,不满足770权限的组要求,也会导致写入失败。
第一次尝试将脚本的日志写入目录修改为绝对路经还不能以Tasker的方式自动运行,然后通过AI分析出以上三个原因。
三、解决方案探索:绕开SELinux的坑,找到安全写入路径
明确问题后,核心需求就变成了:在不触发安全检测、不降低系统安全性的前提下,让Tasker的SU执行的脚本能正常写入日志。我先后尝试了两种思路,最终找到了最优解。
1. 首次尝试:修改SELinux策略(放弃,风险过高)
最直接的想法是修改SELinux策略,放行Tasker的写文件操作。查资料发现有两种方式:一是在脚本中添加setenforce 0临时关闭SELinux(执行完再恢复),二是编写.te策略文件永久放行。但这两种方式都有严重问题:
- 临时关闭SELinux:会被Native Detector等安全检测工具通过安全日志识别,设备直接被标记为“高风险”,即使重新恢复为强制模式也会保留该问题,如果某敏感的APP也有类似的检测策略,则会闪退;且若脚本执行中意外退出,SELinux无法恢复为强制模式,则会被金融类APP认为不安全,出现闪退。
- 编写.te策略文件:需要将策略文件放在系统目录,容易被安全工具扫描到;且部分国产手机厂商的固件甚至不允许自定义策略注入,不一定能修改成功。而且要实现特定应用的写入权限,还要通过adb命令来查询其标签,很麻烦。
2. 最优解:利用/data/adb目录的特殊性,实现安全写入
陷入僵局时,我突然想到:我的Root环境是基于SukiSU(KernelSU)的,而/data/adb/是KernelSU等Root工具的专属数据区。按照Root工具的设计逻辑,这个目录对SU环境下的进程应该有完整的读写权限,且SELinux会默认放行相关操作。
抱着试试的心态,我修改了脚本中的日志写入路径,将原来的其它位置的绝对路径,替换为/data/adb/logs/(ADB下的子目录),同时优化了脚本逻辑:
修改后通过Tasker执行脚本,打开/data/adb/logs/battery_charge.log查看——日志成功写入!且多次测试后,而检测应用的没有出现新问题,银行APP也正常打开。
四、收尾优化:修复日志内容问题,完成Tasker自动化配置
解决了日志写入问题后,最终日志只有开头部分,为了定位问题,我在Tasker中把脚本错误输出捕获到变量里,通过查看变量内容,发现是部分命令不兼容,导致脚本出错,无法完成最后一步——将最后一屏的输出写入到日志。调整脚本命令顺序后,日志内容恢复正常。
最后完成Tasker的自动化配置,确保脚本在“充电结束时”自动执行:
- 创建触发配置文件:选择“状态-电源-电源”,仅勾选“交流电源”。
- 添加防重复执行逻辑:通过自定义变量
%CHARGE记录充电状态,确保每次充电开始仅执行一次脚本,避免重复写入日志。 - 创建对应任务:新建“充电日志记录”任务。第一步,添加“运行Shell”动作,命令为
sh /sdcard/ROM/script/battery_script.sh,勾选“使用Root权限”,条件为%CHARGE~0。第二步添加“变量定义”动作,%CHARGE赋值为1 - 创建退出任务:添加“变量定义”动作,
%CHARGE赋值为0,即再次通电时,条件是可通过的。
五、总结与避坑要点
这次解决Tasker以SU权限运行脚本写入日志的问题的核心,是认清了“Tasker的SU与终端SU的执行上下文差异”,并找到了/data/adb/这个规避SELinux限制的安全路径。最后总结几个关键避坑点,帮大家少走弯路:
- 不要依赖相对路径:Tasker运行脚本的默认工作目录是根目录,脚本中所有文件操作必须用绝对路径。
- 慎用关闭SELinux的操作:尤其是Android 16等新系统,不仅容易触发安全检测,还可能因内核限制导致操作无效。
- 优先选择/data/adb目录:对于Root用户,这个目录是写入日志、存放脚本的最优选择,兼顾安全性和兼容性。
- 脚本权限要匹配:若使用770权限,需确保脚本的所属组是
shell(通过chown root:shell 脚本路径设置),避免TaskerSU执行时权限不匹配。
现在,我的电池检测脚本会在每次充电开始时自动执行,充电结束后自动停止,最后将日志安全地存放在/data/adb/logs/中,我不用再时刻关注电池状态,彻底摆脱了电池焦虑。如果你也有类似的自动化脚本需求,希望这篇文章能帮到你!




评论