执行 exec 命令后 Android 应用程序崩溃

Posted

技术标签:

【中文标题】执行 exec 命令后 Android 应用程序崩溃【英文标题】:Android app crashing after executing exec commands 【发布时间】:2021-02-18 07:22:14 【问题描述】:

我有以下代码,用于自动更新应用程序,它像系统应用程序一样安装在有根设备上。它从已下载新 apk 文件的 copyToPrivateApps 开始。它从协程范围附加到 IO 线程

fun copyToPrivateApps(context: Context, apkPath: String?) 
sudoForCommandAndResult("mount -o rw,remount /system")
sudoForCommandAndResult("mkdir $systemFolder")
sudoForCommandAndResult("cat $apkPath > $systemApkPath")
sudoForCommandAndResult("cp -R $sudoForResult("find ./data/app -name $context.packageName*").drop(1) + "/lib" $systemFolder")
sudoForCommandAndResult("chmod -R 755 $systemFolder")
sudoForCommandAndResult("chmod 644 $systemFngFolder")
sudoForCommandAndResult("chmod 644 $systemSilFolder")
sudoForCommandAndResult("chmod 644 $systemApkPath")
sudoForCommandAndResult("mount -o ro,remount /system")

fun sudoForCommandAndResult(string: String): String 
var res = ""
var outputStream: DataOutputStream? = null
var response    : InputStream? = null
var error       : InputStream? = null
try 
    val su = Runtime.getRuntime().exec("su")
    outputStream = DataOutputStream(su.outputStream)
    response = su.inputStream
    error = su.errorStream

    outputStream.writeBytes(string + "\n")
    outputStream.flush()

    outputStream.writeBytes("exit\n")
    outputStream.flush()
    try 
        su.waitFor()
     catch (e: Throwable) 
        e.printStackTrace()
    

    val responseString = readFully(response!!).replace("su:main", "").trim()
    val errorString    = readFully(error!!).replace("su:main", "").trim()
    res =  logTimeFormat.format(Date()) + string + if(responseString.isNotBlank()) "\n" + logTimeFormat.format(Date()) + responseString else ""
    res += if(errorString.isNotBlank()) "\n" + logTimeFormat.format(Date()) + errorString else ""
 catch (e: Throwable) 
    res += logTimeFormat.format(Date()) + e.message?.trim()
    e.printStackTrace()
 finally 
    Closer.closeSilently(outputStream, response)

return res

fun sudoForResult(string: String): String 
var res = ""
var outputStream: DataOutputStream? = null
var response    : InputStream? = null
var error       : InputStream? = null
try 
    val su = Runtime.getRuntime().exec("su")
    outputStream = DataOutputStream(su.outputStream)
    response = su.inputStream
    error = su.errorStream

    outputStream.writeBytes(string + "\n")
    outputStream.flush()

    outputStream.writeBytes("exit\n")
    outputStream.flush()
    try 
        su.waitFor()
     catch (e: Throwable) 
        e.printStackTrace()
    

    val responseString = readFully(response!!).replace("su:main", "").trim()
    val errorString    = readFully(error!!).replace("su:main", "").trim()
    res =  listOf(responseString, errorString).joinToString(separator = " ")
 catch (e: Throwable) 
    res += e.message?.trim()
    e.printStackTrace()
 finally 
    Closer.closeSilently(outputStream, response)

return res.trim()

尝试执行“cp”命令时,在 val su = Runtime.getRuntime().exec("su") 内 sudoForResult() 失败 出现以下错误: A/libc:致命信号 4 (SIGILL),代码 1,tid 6974 中的故障地址 0x7f6190fa24 (DefaultDispatch)

还有一些奇怪的警告

W/art: 失败的 execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime- arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m -j3 --instruction-set-variant=generic --instruction-set-features=默认 --dex-file=/system/priv-app/appName/appName.apk --oat-file=/data/dalvik-cache/arm64/system@priv-app@appName@appName.apk@classes.dex)因为非0退出状态

有时它甚至更早在“cat”命令上崩溃并出现类似错误

编辑:这在以前使用较小的更新 apk 文件时有效,现在它几乎大了 3 倍。

【问题讨论】:

【参考方案1】:

试试这个:

sudoForCommandAndResult("chmod +x $systemFolder")
sudoForCommandAndResult("chmod +x $systemApkPath")
//change cat command with dd if
sudoForCommandAndResult("dd if=$apkPath of=$systemApkPath")

【讨论】:

是的,它应该拥有所有需要的权限,因为它以前可以工作 @Tomerikoo 是的,我想发表评论,但我应该有 50 个代表。为什么你放弃投票

以上是关于执行 exec 命令后 Android 应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

【exec】shell脚本中的 exec 命令

shell中exec命令的使用

shell脚本中的 exec 命令

system函数与exec函数区别(system需先启动一个shell才能运行指定命令,调用system函数执行指定命令,原进程等待,之后继续运行;调用exec函数开启新进程后,原进程将被直接关闭)

Linux 命令(226)—— exec 命令(builtin)

Linux 命令(226)—— exec 命令(builtin)