按包名查找正在运行的进程ID

时间:2013-03-25 06:25:31

标签: android adb

我正在编写一个脚本,我需要提供应用程序的PID。我可以通过以下命令列出所有进程及其PID,并可以看到我的应用程序的输入。

  

adb shell ps

这给了我一个巨大的进程列表。我需要一个条目(我可以进一步提供给另一个命令),所以我想用包名过滤这个结果。 grep命令在我的Windows机器上不起作用。也尝试了以下命令,但它没有帮助。

  

adb shell ps name:my_app_package

4 个答案:

答案 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

一步一步:

  1. 在连接设备(或仿真器)时输入adb shell命令。
    (执行此命令后,命令行前缀为shell@android:/ $。)

  2. 输入ps | grep <package_name_to_be_filtered>(即ps | grep com.google)。


  3. 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选项少。