Android设备adb shell命令行提示符定制修改

如何定制修改安卓adb shell的命令行提示符
Views: 166
3 0
Read Time:2 Minute, 26 Second

当我们通过adb shell进入Android的shell环境时,命令行左侧都会显示当前的设备名。如下所示:

c1200:/ $

在Linux环境下,当我们通过SSH连接进入Linux Shell时,命令行左侧同样会显示当前设备的名称,不同的是,Linux环境下显示的设备名称,其实是对应当前Linux设备的Hostname与User相结合,而安卓默认的命令行提示符则简单一些。

在Linux环境中,命令行提示符的显示由PS1环境变量决定,Android内同样如此,这里我们查看一下PS1环境变量:

PS C:\Users\bst> adb shell
c1200:/ # echo $PS1
${| local e=$? (( e )) && REPLY+="$e|" return $e }$USER@$HOSTNAME:${PWD:-?} #
c1200:/ #

该环境变量的值设定的含义具体解析如下:

${| … }:这是一种形式的命令替换,它执行其中的命令并将其输出作为字符串插入到PS1中。在这个情况下,整个 ${| … } 结构实际上是用来设置提示符的。

local e=$?:这一行声明了一个局部变量 e 来存储上一个命令的退出状态,熟悉shell的朋友应该知道$? 是一个特殊变量,保存了上一个执行命令的退出状态码。

(( e )) && REPLY+=”$e|”:这是一个条件表达式,它检查变量 e 的值是否为非零。如果是,它将上一个命令的退出状态码附加到提示符字符串 REPLY 中,以及一个竖线(|),表示非零退出状态码。

return $e:这一行会返回上一个命令的退出状态码。这意味着,如果前一个命令失败(退出状态码非零),那么整个提示符将会包含该失败命令的退出状态码,并且Shell的退出状态码将会被设置为该值。

$HOSTNAME:这是主机名变量,用于显示当前主机的名称。

${PWD:-?}:这是当前工作目录的变量。${PWD} 会显示当前工作目录的绝对路径。如果当前工作目录无法获取,它会显示一个问号(?)作为占位符。

所以,综上所述,这个 PS1 设置的含义是:显示主机名、当前工作目录的绝对路径,并在提示符中显示上一个命令的退出状态码(如果存在),以及一个竖线分隔符;那么PS1是如何被设置的呢,关于这部分的设置逻辑,这里我们需要参考sh的源码:

//external/mksh/src/main.c
if (Flag(FLOGIN))
            include(substitute("$HOME/.profile", 0), 0, NULL, true);
if (Flag(FTALKING)) {
       cp = substitute("${ENV:-" MKSHRC_PATH "}", DOTILDE);
       if (cp[0] != '\0')
          // include属于自定义函数
          include(cp, 0, NULL, true);
}

//include为自定义实现的函数,实现了对shell环境变量的配置
include(const char *name, int argc, const char **argv, bool intr_ok)
{
    Source *volatile s = NULL;
    struct shf *shf;
    const char **volatile old_argv;
    volatile int old_argc;
    int i;

    shf = shf_open(name, O_RDONLY | O_MAYEXEC, 0, SHF_MAPHI | SHF_CLEXEC);
    if (shf == NULL)
        return (-1);

    if (argv) {
        old_argv = e->loc->argv;
        old_argc = e->loc->argc;
    } else {
        old_argv = NULL;
        old_argc = 0;
    }
    newenv(E_INCL);
    if ((i = kshsetjmp(e->jbuf))) {
        quitenv(s ? s->u.shf : NULL);
        if (old_argv) {
            e->loc->argv = old_argv;
            e->loc->argc = old_argc;
        }
        switch (i) {
        case LRETURN:
        case LERROR:
        case LERREXT:
            /* see below */
            return (exstat & 0xFF);
        case LINTR:
            /*
             * intr_ok is set if we are including .profile or $ENV.
             * If user ^Cs out, we don't want to kill the shell...
             */
            if (intr_ok && ((exstat & 0xFF) - 128) != SIGTERM)
                return (1);
            /* FALLTHROUGH */
        case LEXIT:
        case LLEAVE:
        case LSHELL:
            unwind(i);
            /* NOTREACHED */
        default:
            internal_errorf(Tunexpected_type, Tunwind, Tsource, i);
            /* NOTREACHED */
        }
    }
    if (argv) {
        e->loc->argv = argv;
        e->loc->argc = argc;
    }
    s = pushs(SFILE, ATEMP);
    s->u.shf = shf;
    strdupx(s->file, name, ATEMP);
    i = shell(s, 1);
    quitenv(s->u.shf);
    if (old_argv) {
        e->loc->argv = old_argv;
        e->loc->argc = old_argc;
    }
    /* & 0xff to ensure value not -1 */
    return (i & 0xFF);
}

这里MKSHRC_PATH的值为/system/etc/mkshrc,其内容为:

set +o nohup
if (( USER_ID )); then PS1='$'; else PS1='#'; fi
PS4='[$EPOCHREALTIME] '; PS1='${|
    local e=$?
    (( e )) && REPLY+="$e|"
    return $e
}$HOSTNAME:${PWD:-?} '"$PS1 "

所以这里PS1的设置逻辑其实是通过sh解析/system/etc/mkshrc文件后配置到环境变量内的。

所以如果我们要修改命令行提示符,可以通过修改/system/etc/mkshrc文件的配置,比如我希望命令行提示符显示当前所属用户(一般情况下为shell用户,adb root之后则为root用户),则可以修改/system/etc/mkshrc为如下所示:

set +o nohup
if (( USER_ID )); then PS1='$'; else PS1='#'; fi
PS4='[$EPOCHREALTIME] '; PS1='${|
    local e=$?
    (( e )) && REPLY+="$e|"
    return $e
}$USER@$HOSTNAME:${PWD:-?} '"$PS1 "

修改的逻辑很简单,其实就是利用$USER环境变量来获取当前用户信息,并将其置于HOSTNAME之前。

之后我们再重新adb shell进入,看看效果:

shell@c1200:/ $

如果我们先adb root,再adb shell进入,会发现命令行提示符为:

root@c1200:/ $

是不是不一样了?是不是很神奇!

除此之后,我们应该还关注到在设置PS1的过程中用到HOSTNAME环境变量,该变量的值一般是与ro.product.device的值保持一致的,而ro.product.device与Android编译配置时的环境变量TARGET_DEVICE保持一致,TARGET_DEVICE的值又与我们的编译配置PRODUCT_DEVICE配置一致;

所以如果我们要修改命令行提示符中的设备标识,一来我们可以修改编译配置时的PRODUCT_DEVICE名称,二来可以修改/system/etc/mkshrc,设定HOSTNAME的值即可。

Happy
Happy
100 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %
FranzKafka95
FranzKafka95

极客,文学爱好者。如果你也喜欢我,那你大可不必害羞。

文章: 86

留下评论

您的电子邮箱地址不会被公开。 必填项已用*标注

zh_CNCN