使用应用程序包名进行adb shell Logcat

20

是否可以在每行日志中同时显示包名?
使用

logcat -v long

命令后,包名字段(PID之后)为空。
我想过滤来自特定应用程序的不同标签的日志,不知道是否可能。


我想为@Alexander发表评论,但显然我只有足够的积分来回答。通过cut -c10-15的管道从整行文本中获取pid。 cut --help - grossdm
1
这个回答解决了你的问题吗?如何在Android中过滤LogCat以仅获取来自我的应用程序的消息? - nima moradi
5个回答

47

logcat记录中没有“包名字段”,因此没有标准/内置的过滤方式。

尽管自Android 7.0以来,您可以使用logcat --pid选项结合pidof -s命令按二进制/包名过滤输出:

adb shell "logcat --pid=$(pidof -s <package_name>)"

Linux/MacOS中将"替换为'


在基于Marshmallow的设备上对我不起作用:$ adb -d shell logcat --pid=6693 Unrecognized Option - Usage: logcat [options] [filterspecs]... 看起来 --pid 不再是一个有效的选项。 - Jules
1
@Jules,logcat --pid是在Nougat中引入的。 - Alex P.
它对我而言是有效的。唯一的问题是,我先要键入“adb shell”,然后在Shell中输入“logcat --pid=$(pidof -s <package_name>)”。 - Majonsi
2
它对我有效。记得在Linux/MacOS中用'替换"。 - Shailesh
2
对于Windows PowerShell: adb logcat --pid=$(adb shell pidof -s <package name>) - rolinger
终于,一个真正有效的答案。谢谢! - rjr-apps

8
这是我的脚本。有点生疏,但仍然有效。
PID=`adb shell ps | grep -i <your package name> | cut -c10-15`;
adb logcat | grep $PID

实际上,我有一个Python脚本来添加更多的颜色,并使用while循环来监视该进程何时重新启动,但我认为你会明白我的意思。


我其实不知道如何使用这个.. 我既不知道如何从命令行启动脚本,也不知道如何在我的Android应用程序中使用它(这正是我想要/需要的)。我目前是通过Runtime.getRuntime().exec("su -c logcat -d -v long");来实现的,但我没有得到包名。 - Felix Plaumann

5

似乎每个人都指向通过PID进行过滤的解决方案。忽略它。正确的方法是通过UID进行过滤,因为UID永久绑定到软件包名称(在崩溃、升级、重新启动等情况下不会更改)。

要查找软件包名称的UID:

adb shell dumpsys package <PACKAGE> | grep userId

它将会打印出类似以下的内容:
    userId=10412

然后将--uid=10412传递给logcat。

很遗憾,Google没有在任何可见的地方记录这个信息,我不得不自己找到它。请点赞以提高可见性。


谢谢你,阿尔巴!大部分时间我使用的是通过标签进行过滤的命令$ logcat -s "TAG:*" "*:S"TAG是一个自定义的字符串,你可以通过你喜欢的日志记录器来使用它。 - undefined

2

选项 1

逐行输入以下内容:

adb shell
su
bash
PKG_PID_LIST_CACHE=$(eval $(pm list packages | cut -d ':' -f 2 | sed 's/^\(.*\)$/echo \"\$\(echo \1\) \$\(pidof \1\)\";/'))
PROC_PID_LIST_CACHE=$(ps -A -o NAME -o PID)
PID_LIST_CACHE=$(echo "$PKG_PID_LIST_CACHE\n$PROC_PID_LIST_CACHE")
function pid2pkg() { pkgName=$(echo "$PID_LIST_CACHE" | grep -w $1 | cut -d ' ' -f1 | head -1); if [ "$pkgName" != "" ] ; then echo $pkgName; else echo "*NOT RUNNING*"; fi }
eval "$(logcat -d | sed -r -e 's/([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +(.*)/\2 \$\(pid2pkg \3\) \5/g' | sed -r -e 's/(.+)/echo -e \"\1\"/g')"

logcat输出将以以下格式呈现:

[Time] [Name] [Type] [Message]

例子:

14:34:59.386 wpa_supplicant E wpa_supplicant: nl80211: Failed to set IPv4 unicast in multicast filter
14:35:02.231 com.android.phone D TelephonyProvider: subIdString = 1 subId = 1
14:35:03.469 android.hardware.wifi@1.0-service E WifiHAL : wifi_get_logger_supported_feature_set: Error -3 happened.
14:35:03.518 system_server I WifiService: getWifiApEnabledState uid=10086
14:35:03.519 dev.ukanth.ufirewall D AFWall  : isWifiApEnabled is false
14:35:03.520 system_server I GnssLocationProvider: WakeLock released by handleMessage(UPDATE_NETWORK_STATE, 0, 123)
14:35:03.522 dev.ukanth.ufirewall I AFWall  : Now assuming wifi connection

一些系统进程没有包名,例如 system_serverwpa_supplicant。如果找不到包名,进程名称将被显示出来。
注意事项:
如果某个 PID 后面的进程已经停止运行,就无法再获取包名/进程名称了。
在一个进程退出自身或设备重新启动后,PID 可能会被重新分配给完全不同的进程。
因此,您可能需要检查进程实际运行的时间:
ps -e -o pid -o stime -o name

选项2

如果你想让格式更易读一些,你可以将我的日志脚本复制到你的设备上并执行:

better_logging.sh

PKG_PID_LIST_CACHE=$(eval $(pm list packages | cut -d ':' -f 2 | sed 's/^\(.*\)$/echo \"\$\(echo \1\) \$\(pidof \1\)\";/'))
PROC_PID_LIST_CACHE=$(ps -A -o NAME -o PID)
PID_LIST_CACHE=$(echo "$PKG_PID_LIST_CACHE\n$PROC_PID_LIST_CACHE")
MAX_LEN=$(echo "$PID_LIST_CACHE" | cut -d ' ' -f1 | awk '{ if ( length > L ) { L=length} }END{ print L}')
function pid2pkg() {
    pkgName=$(echo "$PID_LIST_CACHE" | grep -w $1 | cut -d ' ' -f1 | head -1);
    if [ "$pkgName" != "" ] ; then
        printf "%-${MAX_LEN}s" "$pkgName";
    else
        printf "%-${MAX_LEN}s" "<UNKNOWN (NOT RUNNING)>";
    fi
}

eval "$(\
logcat -d | \
sed -r -e 's/([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +(.*)/\2\ $\(pid2pkg \3\) \5/g' | \
sed -r -e 's/(.+)/echo -e \"\1\"/g' \
)" | \
awk '
function color(c,s) {
    printf("\033[%dm%s\033[0m\n",90+c,s)
}
/ E / {color(1,$0);next}
/ D / {color(2,$0);next}
/ W / {color(3,$0);next}
/ I / {color(4,$0);next}
{print}
'

要复制并运行它,您可以使用:

adb push better_logging.sh /sdcard/better_logging.sh
adb shell "bash /sdcard/better_logging.sh"

输出将如下所示:

log_screenshot


1
有没有不需要 root 的方法来实现这个?在 adb logcat 中将 PID 更新为进程名称将是非常棒的。 - rcmpayne

0

这个可以用 awk 实现。

adb logcat | grep -F "`adb shell ps | grep com.yourpackage  | awk '{print $2;}'`"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接