10

在我的 PC 上的 shell 中,我可以运行adb shell cmd package list packages并获取所有已安装软件包的列表。我想在终端模拟器(当前使用 Termux)中在我的 Android 手机(Nexus 6P)上本地运行此命令和类似命令。

如果我用 打开同一个 shell /system/bin/sh,然后尝试运行/system/bin/cmd package list packages,什么都不会发生(没有错误,只是不输出任何内容并重新加载提示)。

如果我运行/system/bin/cmd -l选项列表,则会按预期显示。$PATH并且$LD_LIBRARY_PATH在两种环境中都是相同的。一个主要区别是从 中echo $USER返回“shell” ,但从Termux 启动时adb shell返回我的本地用户名。/system/bin/sh

有什么方法可以复制adb shell在 Android 本地终端模拟器中运行的命令的行为?

编辑:我的设备已植根,我可以使用仅根解决方案。

4

5 回答 5

5

问题是 Termux。按照设计,Termux 只运行(或大部分?)Linux 命令行程序,这些程序是您使用 apt 或更新的“本机”包管理界面(例如 apt install bsdtar)在 Termux 中安装的。运行 adb shell 命令所需的是一个终端模拟器,它可以真正访问底层的 Android 文件系统,而不仅仅是 Termux,它实际上是一个 chroot 保存,因为它知道它不是从文件系统根 /. 运行命令。

作为一个简单的测试,运行以下命令:

    which ls

它应该返回类似/system/bin/ls. 但是,如果它返回类似的东西,/data/data/com.termux/files/usr/bin/applets/ls那么您必须将终端仿真器更改为其他东西。我怀疑 Termux 的设计目的是考虑到 Google 在 KitKat 或 Android 4.X 之后实施的更严格的 shell 执行策略。

我正在使用的 Android 发行版 LineageOS 14.1 带有一个内置的 shell 模拟器,它允许我运行 /system/bin/ls 中的命令。

于 2018-04-16T18:39:33.730 回答
5

我手边没有扎根的 Nougat 设备,但类似以下内容可能足够接近adb shell(假设您使用的是 SuperSU):

env -i USER=shell "$(PATH=/system/xbin:/system/bin:/su/bin:/sbin:/magisk/.core/bin which su)" shell --context u:r:shell:s0 --shell /system/bin/sh --command COMMAND

我(非常简短地)从 Termux 在有根的 Marshmallow 设备上对其进行了测试。

详细说明:

  • -i标志用于从空环境开始
  • USER=shell不是特别需要,但由于某种原因su拒绝在完全空的环境中运行
  • $(PATH=/system/xbin:/system/bin:/su/bin:/sbin:/magisk/.core/bin which su)指向设备上 su 二进制文件的完整路径,如果您愿意,可以硬编码
  • shell指示su二进制文件以 shell 用户身份登录(与 相同adb shell
  • --context u:r:shell:s0设置适当的 SELinux 上下文
  • --shell /system/bin/sh指示 SuperSU 使用系统 shell 而不是它自己的sushshell

另一种选择是从设备实际运行 adb,通过 TCP 连接到自身。如果您需要一些只能通过 adb 获得的功能(例如在我的情况下它是adb forward),那么这可能是您唯一的选择。不幸的是,这不是特别方便。

我无法使用任何公开可用的 adb 二进制文件获得成功,因此我自己构建了它并进行了一些小的更改。您可以分别在https://github.com/shakalaca/fastboot-adb-androidhttps://github.com/brbsix/fastboot-adb-android看到我使用的来源和所做的更改。

安装 adb 后,这是我用来连接设备的命令的简短列表:

# Add iptables rules to block external connections to port 9999'
su root iptables -N adbd
su root iptables -A adbd -i lo -p tcp -m tcp --dport 9999 -j ACCEPT
su root iptables -A adbd -p tcp -m tcp --dport 9999 -j DROP
su root iptables -A INPUT -j adbd

# Necessary in order to display authorization prompt
su shell setprop ro.debuggable 1

su shell setprop service.adb.tcp.port 9999

su root start adbd

adb connect 127.0.0.1:9999

adb wait-for-local-device

去关机:

adb kill-server
su root stop adbd
su shell setprop ro.debuggable 0
su shell setprop service.adb.tcp.port 0
su root iptables -D INPUT -j adbd
su root iptables -F adbd
su root iptables -X adbd
于 2017-12-04T21:29:01.323 回答
2

所以我最近尝试了这个......如果你有根,你可以使用终端模拟器。

  • 然后你想要的命令没有“adb shell”部分。

我尝试了命令“adb shell dumpsys deviceidle force-idle”以强制设备进入休眠状态。我通过终端仿真器在设备上执行此操作:“dumpsys deviceidle force-idle”并且它确实生效了。dumpsys batterystats 命令也有效。

小心带有大量文本输出的命令,因为屏幕会被输出淹没并且会在一段时间内无响应。

于 2020-08-06T17:43:36.897 回答
0

编辑termux我最初在没有考虑标签的 情况下回答了这个问题。在尝试在香草模拟器上执行 shell 命令时,这对我有用,并且在研究时看到了这个问题,所以我尝试以不同的方式回答它。

你几乎在你的问题中有它。您只需要执行sh

int result = -1;
try {
    final Process shell = Runtime.getRuntime().exec("sh");
    final DataOutputStream commands = new DataOutputStream(shell.getOutputStream());
    commands.writeBytes("write a series");
    commands.writeBytes("of commands here");
    commands.writeBytes("exit\n");
    commands.flush();
    result = shell.waitFor();
  }
} catch (Exception e) {
  e.printStackTrace();
}

如果result == 0命令成功,否则

于 2019-06-26T06:49:10.347 回答
-1
  • 只植根安卓
  • 必须安装 Busybox(尽管您可以尝试不安装)

只写不带前缀的普通命令adb

于 2019-11-01T17:42:58.963 回答