我正在编写一个脚本,我需要提供应用程序的PID。我可以通过以下命令列出所有进程及其PID,并可以看到我的应用程序的输入。
adb shell ps
这给了我一个巨大的进程列表。我需要一个条目(我可以进一步提供给另一个命令),所以我想用包名过滤这个结果。 grep命令在我的Windows机器上不起作用。也尝试了以下命令,但它没有帮助。
adb shell ps name:my_app_package
答案 0 :(得分:22)
由于Android 7.0是按包名查找进程ID的最简单方法,因此使用pidof
命令:
usage: pidof [-s] [-o omitpid[,omitpid...]] [NAME]...
Print the PIDs of all processes with the given names.
-s single shot, only return one pid.
-o omit PID(s)
就这样运行:
adb shell pidof my.app.package
在7.0之前的Android中,人们使用ps
命令,然后使用comm
值的内置过滤器解析其输出(对于Android应用程序是包名称的最后15个字符)或{ {1}}命令。如果名称的最后15个字符以数字开头,则grep
过滤器不起作用,默认情况下不包括comm
,直到Android 4.2。但即使找到了正确的生产线,仍然需要提取grep
值。
有多种方法可以做到这一点。以下是使用单个PID
命令查找进程和提取PID的方法:
sed
问题是,在Android 6.0之前,默认情况下并未包含adb shell "ps | sed -n 's/^[^ ]* *\([0-9]*\).* my\.app\.package$/\1/p'"
。
但如果您必须使用旧设备,则可以始终使用以下Android版本独立解决方案。它不使用任何外部命令 - 只是Android shell内置命令:
sed
查找PID的最常见原因是在adb shell "for p in /proc/[0-9]*; do [[ $(<$p/cmdline) = my.app.package ]] && echo ${p##*/}; done"
等其他命令中使用它。假设我们有多个kill
运行的实例,我们希望一次完成它们。只需在最后一个命令中将logcat
替换为echo
:
kill -2
如果从Linux / OSX shell运行命令,则将adb shell "for p in /proc/[0-9]*; do [[ $(<$p/cmdline) = logcat ]] && kill -2 ${p##*/}; done"
替换为"
。
答案 1 :(得分:11)
首先输入adb shell ps
,然后使用adb shell
,而不是ps
。
一步一步:
在连接设备(或仿真器)时输入adb shell
命令。
(执行此命令后,命令行前缀为shell@android:/ $
。)
输入ps | grep <package_name_to_be_filtered>
(即ps | grep com.google
)。
C:> adb shell
shell@android:/ $ ps | grep com.google
u0_a64 3353 2467 903744 52904 ffffffff 00000000 S com.google.process.location
u0_a64 3426 2467 893964 49452 ffffffff 00000000 S com.google.process.gapps
答案 2 :(得分:0)
Alex P.'s answer从技术上回答了“通过进程名查找正在运行的进程ID”而不是“通过包名查找正在运行的进程ID”的问题>”。区别很细微,并且通过<activity>
标签中的“ android:process”属性在进程重命名中体现出来。
我担心正确的解决方案会涉及更多问题,您可以阅读Android Studio为找到真实进程名称here而采取的解决方法。您将在resolveLegacyPid
下看到与Android Oreo之前版本相关的Shell脚本,对于Android Oreo +则为resolveApplicationId
,看到以下脚本:
/** * Asynchronously resolves to the application ID. The application ID is the package name that is * ultimately given to the application on the device, which usually comes from the manifest. * Note that this may be different from {@link ClientData#getClientDescription()} or * {@link ClientData#getPackageName()} due to the manifest containing a process rename XML * option via "android:process". * * <p>When the manifest option is specified, the two aforementioned {@link ClientData }methods * will return the process name, not the application ID. Therefore, this method guarantees the * application ID if it's possible to resolve. Only if it's not possible will this fall back to * using the process name instead. */ private void resolveApplicationId(@NotNull Process process) { myResolverExecutor.execute(() -> { String command = String.format(Locale.US, "stat -c %%u /proc/%d | xargs -n 1 cmd package list packages --uid", process.getPid()); CollectingOutputReceiver receiver = new CollectingOutputReceiver(); try { myIDevice.executeShellCommand(command, receiver); } catch (IOException | TimeoutException | AdbCommandRejectedException | ShellCommandUnresponsiveException e) { Logger.getInstance(Device.class).warn("Could not resolve application ID", e); return; } String output = receiver.getOutput(); if (output.isEmpty()) { return; } Matcher m = PACKAGE_NAME_PATTERN.matcher(output); while (m.find()) { process.addApplicationId(m.group(1)); } }); } @NotNull private Future<Void> resolveLegacyPid(@NotNull String applicationId) { return myResolverExecutor.submit( () -> { // This shell command tries to retrieve the PID associated with a given application ID. // To achieve this goal, it does the following: // // 1) Gets the user name (e.g. u0_a01) using run-as with the application ID and // the whoami command. // 2) Runs the ps command under the application ID to get a list of all running // processes running under the user associated with the given application ID. // The output of ps looks something like: "<user> <pid> ..." // 3) The output of ps is piped into grep/tr/cut to parse out the second parameter, // of each line, which is the PID of each process. // 4) The PID is then used in the readlink command to follow the symbolic links of // the symlinked exe file under the PID's /proc directory. // 5) If the symlink resolves to any of the 32 or 64 bit zygote process, the PID is // printed to the console, serving as the output of the script. String command = String.format( "uid=`run-as %s whoami` && " + "for pid in `run-as %s ps | grep -o \"$uid[[:space:]]\\{1,\\}[[:digit:]]\\{1,\\}\" | tr -s ' ' ' ' | cut -d ' ' -f2`; do " + " if [[ `run-as %s readlink /proc/$pid/exe` == /system/bin/app_process* ]]; then " + " echo $pid; " + " fi; " + "done", applicationId, applicationId, applicationId); CollectingOutputReceiver receiver = new CollectingOutputReceiver(); myIDevice.executeShellCommand(command, receiver); String output = receiver.getOutput(); if (output.isEmpty()) { return null; } String[] lines = output.split("\n"); // We only handle the first return value for now. try { for (String line : lines) { int pid = Integer.parseInt(line.trim()); myPidToProcess.computeIfPresent(pid, (ignored, process) -> { process.addApplicationId(applicationId); return process; }); } } catch (NumberFormatException ignored) { } return null; }); }
答案 3 :(得分:-1)
ps显示的进程可以限制为属于任何给定用户的进程,方法是通过grep(一种用于搜索文本的过滤器)输出输出。例如,属于具有用户名adam的用户的进程可以使用以下内容显示:
ps -ef | grep adam
-e选项生成有关当前正在运行的每个进程的信息列表。 -f选项生成的列表包含的每个进程的信息项比-l选项少。