简体   繁体   English

如何在 Android 设备本地的终端模拟器中运行“adb shell”命令?

[英]How do I run "adb shell" commands in a terminal emulator locally on an Android device?

From a shell on my PC, I can run adb shell cmd package list packages , and get a list of all installed packages.从我 PC 上的 shell,我可以运行adb shell cmd package list packages ,并获取所有已安装包的列表。 I would like to run this and similar commands locally on my Android phone (Nexus 6P) in a terminal emulator (currently using Termux).我想在我的 Android 手机(Nexus 6P)上的终端模拟器(目前使用 Termux)中本地运行这个和类似的命令。

If I open the same shell with /system/bin/sh , and then try to run /system/bin/cmd package list packages , nothing happens (no errors, just outputs nothing and reloads the prompt).如果我使用/system/bin/sh打开相同的外壳,然后尝试运行/system/bin/cmd package list packages ,则不会发生任何事情(没有错误,只是不输出任何内容并重新加载提示)。

If I run /system/bin/cmd -l the list of options appears as expected.如果我运行/system/bin/cmd -l选项列表会按预期显示。 $PATH and $LD_LIBRARY_PATH are the same in both environments. $PATH$LD_LIBRARY_PATH在两种环境中是相同的。 One major difference is that echo $USER returns "shell" from adb shell , but returns my local username from /system/bin/sh launched from Termux.一个主要区别是echo $USERadb shell返回“shell”,但从 Termux 启动的/system/bin/sh返回我的本地用户名。

Is there any way to replicate the behavior of commands run from adb shell in a terminal emulator locally on Android?有什么方法可以在 Android 本地的终端模拟器中复制从adb shell运行的命令的行为?

Edit: My device is rooted, and I am OK with root only solutions.编辑:我的设备已植根,我可以使用仅限 root 的解决方案。

I don't have a rooted Nougat device handy, but something like the following may be a close enough approximation to adb shell (assuming you are using SuperSU): 我没有方便的植根的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

I (very briefly) tested it from Termux on a rooted Marshmallow device. 我(非常简短地)在有根的棉花糖设备上从Termux进行了测试。

To elaborate: 详细说明:

  • the -i flag is used to start with an empty environment -i标志用于从空环境开始
  • USER=shell isn't specifically required, but for some reason su refuses to run with a completely empty environment 不需要USER=shell ,但是出于某种原因su拒绝在完全空的环境下运行
  • $(PATH=/system/xbin:/system/bin:/su/bin:/sbin:/magisk/.core/bin which su) points to the full path of the su binary on your device and can be hardcoded if you prefer $(PATH=/system/xbin:/system/bin:/su/bin:/sbin:/magisk/.core/bin which su)指向设备上su二进制文件的完整路径,如果您将其硬编码偏爱
  • shell instructs the su binary to login as the shell user (the same as adb shell ) shell指示su二进制文件以shell用户身份登录(与adb shell相同)
  • --context u:r:shell:s0 sets the appropriate SELinux context --context u:r:shell:s0设置适当的SELinux上下文
  • --shell /system/bin/sh instructs SuperSU to use the system shell rather than it's own sush shell --shell /system/bin/sh指示SuperSU使用系统外壳而不是其自身的sush Shell

Another option would be to actually run adb from the device, connecting to itself over TCP. 另一个选择是从设备实际运行adb,并通过TCP连接到其自身。 If you need some functionality that is only available via adb (eg in my case it was adb forward ) then this may be your only option. 如果您需要某些只能通过adb使用的功能(例如,在我的情况下为adb forward ),那么这可能是您唯一的选择。 Unfortunately this isn't particularly convenient. 不幸的是,这并不是特别方便。

I wasn't able to find success with any publicly available adb binaries, so I build it myself with a few minor changes. 我无法通过任何公共可用的adb二进制文件获得成功,因此我自己做了一些小改动就构建了它。 You can see the sources I used and the changes I made at https://github.com/shakalaca/fastboot-adb-android and https://github.com/brbsix/fastboot-adb-android , respectively. 您可以分别在https://github.com/shakalaca/fastboot-adb-androidhttps://github.com/brbsix/fastboot-adb-android上查看我使用的源和所做的更改。

Once you have adb installed, here's an abbreviated list of commands I used to connect to the device: 一旦安装了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

To shut down: 去关机:

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

The problem is Termux. 问题是Termux。 By design, Termux runs only (or is mostly?) the Linux command line programs that you install from within Termux using apt or the newer "native" package management interface, eg apt install bsdtar. 根据设计,Termux仅运行(或主要是?)使用apt或较新的“本机”程序包管理界面从Termux中安装的Linux命令行程序,例如apt install bsdtar。 What you need to run the adb shell commands is a terminal emulator that can truly access the underlying Android file system, not just the Termux that is practically a chroot save for the fact that it's aware it's not running commands from the filesystem root /. 运行adb shell命令所需的是一个终端仿真器,它可以真正访问基础的Android文件系统,而不仅仅是Termux(实际上是chroot),因为它知道它不是从文件系统root /运行命令。

As a simple test, run the following command: 作为一个简单的测试,运行以下命令:

    which ls

It should return something like /system/bin/ls . 它应该返回类似/system/bin/ls But if it returns something like /data/data/com.termux/files/usr/bin/applets/ls then you have to change your terminal emulator to something else. 但是,如果它返回类似/data/data/com.termux/files/usr/bin/applets/ls则必须将终端仿真器更改为其他内容。 I suspect that Termux was designed to take into account the more restrictive shell execution policies that Google put into place after KitKat or the Android 4.X. 我怀疑Termux旨在考虑Google在KitKat或Android 4.X之后实施的限制性更强的Shell执行策略。

The Android distribution I'm using, LineageOS 14.1, comes with a built-in shell emulator that allows me to run commands found in /system/bin/ls. 我正在使用的Android发行版LineageOS 14.1带有内置的外壳模拟器,可让我运行/ system / bin / ls中的命令。

So I tried this recently...if you're rooted you can use a terminal emulator.所以我最近尝试了这个......如果你已经扎根,你可以使用终端模拟器。

  • su
  • then the command you want without "adb shell" part of it.然后是你想要的没有“adb shell”部分的命令。

i tried the command "adb shell dumpsys deviceidle force-idle" in order to force device into doze.我尝试了命令“adb shell dumpsys deviceidle force-idle”以强制设备进入瞌睡。 I did this on the device via terminal emulator as: "dumpsys deviceidle force-idle" and it did take effect.我通过终端模拟器在设备上执行此操作:“dumpsys deviceidle force-idle”并且它确实生效了。 also the dumpsys batterystats command worked. dumpsys batterystats 命令也有效。

be careful with commands with extensive text output, as the screen will be flooded with the output and will be unresponsive for some time.小心带有大量文本输出的命令,因为屏幕会被输出淹没并且在一段时间内没有响应。

EDIT I originally answered this without the termux tag in mind. 编辑我最初回答这个问题时没有termux标签。 This worked for me while trying to execute shell commands on a vanilla emulator and saw this question while researching, so I tried to answer it differently. 这在尝试在香草模拟器上执行shell命令时对我有用,并且在研究时看到了这个问题,因此我尝试以不同的方式回答。

You almost had it there in your question. 您的问题几乎就在那里。 You only need to execute sh : 您只需要执行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();
}

If result == 0 the commands were succesful, else otherwise 如果result == 0则命令成功,否则,否则

  • Only rooted android 仅植根于Android
  • Busybox must be installed (though you can try without it) 必须安装Busybox(尽管您可以尝试不使用它)

Just write the normal command without the prefix adb 只需编写不带前缀adb的普通命令

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM