2
0

More than 3 years have passed since last update.

xonshでscreenfetchするとpythonx.xって出て悲しい

Last updated at Posted at 2019-12-29
$ screenfetch
           /:-------------:\          user@host
        :-------------------::        OS: Fedora 30 Thirty
      :-----------/shhOHbmp---:\      Kernel: x86_64 Linux 5.3.16-200.fc30.x86_64
    /-----------omMMMNNNMMD  ---:     Uptime: 13h 27m
   :-----------sMMMMNMNMP.    ---:    Packages: 2531
  :-----------:MMMdP-------    ---\   Shell: python3.8
 ,------------:MMMd--------    ---:   Resolution: 1920x1080
 :------------:MMMd-------    .---:   DE: GNOME 
 :----    oNMMMMMMMMMNho     .----:   WM: GNOME Shell
 :--     .+shhhMMMmhhy++   .------/   WM Theme: Adwaita
 :-    -------:MMMd--------------:    GTK Theme: Adwaita [GTK2/3]
 :-   --------/MMMd-------------;     Icon Theme: Adwaita
 :-    ------/hMMMy------------:      Font: Cantarell 11
 :-- :dMNdhhdNMMNo------------;       CPU: Intel Core i7-8550U @ 8x 4GHz
 :---:sdNMMMMNds:------------:        GPU: Mesa DRI Intel(R) UHD Graphics 620 (Kabylake GT2) 
 :------:://:-------------::          RAM: 6817MiB / 15779MiB
 :---------------------://            

Shell:を見ての通りちょっと悲しい。そもそもscreenfetchってどうシェルをとってるんだ?と思ったので読む話。あとできればXonshって表示してほしい。

screenfetchを読もう

screenfetch:GitHub

screenfetchって1つのシェルスクリプトなんですね・・・こわ
どうやらscreenfetch-devってのが本体っぽい。

で、シェル関係が知りたいのでshellでCtrl+F。

すると黄色具合から1843行目のdetectshell()があやしい。

とりあえず読んでみよう

ひとまず前半を示す。

detectshell () {
    if [[ ! "${shell_type}" ]]; then
        if [[ "${distro}" == "Cygwin" || "${distro}" == "Msys" || "${distro}" == "Haiku" || "${distro}" == "Alpine Linux" ||
            "${distro}" == "Mac OS X" || "${distro}" == "TinyCore" || "${distro}" == "Raspbian" || "${OSTYPE}" == "gnu" ]]; then
            shell_type=$(echo "$SHELL" | awk -F'/' '{print $NF}')
        elif readlink -f "$SHELL" 2>&1 | grep -q -i 'busybox'; then
            shell_type="BusyBox"
        else
            if [[ "${OSTYPE}" =~ "linux" ]]; then
                shell_type=$(tr '\0' '\n' </proc/$PPID/cmdline | head -1)
            elif [[ "${distro}" =~ "BSD" ]]; then
                shell_type=$(ps -p $PPID -o command | tail -1)
            else
                shell_type=$(ps -p "$(ps -p $PPID | awk '$1 !~ /PID/ {print $1}')" | awk 'FNR>1 {print $1}')
            fi
            shell_type=${shell_type/-}
            shell_type=${shell_type//*\/}
        fi
    fi

        .....

    myShell=${shell_type}
    verboseOut "Finding current shell...found as '$myShell'"
}

実際-vオプションをつけて見てみるとverboseOut "Finding current shell...found as '$myShell'"の行が動いてることがわかる。

まずは最初のifの中を見よう。

$shell_typeってのがシェル_タイプの変数っぽい(小泉進次郎風に)。
まずはOSの種類を見てからOSにあわせてシェルを取得してるっぽい。
OSの種類はlinuxなのでif [[ "${OSTYPE}" =~ "linux" ]]のブロックを見よう。ちなみに=~は正規表現比較らしい。いま知った。

まあ見たらわかるように、tr '\0' '\n' </proc/$PPID/cmdline | head -1がシェル_タイプってこと。後ろでちょっと加工してるけどまあそれはまた後に。

/proc/$PPID/cmdlineは、大体名前から察するように$PPIDのプロセスのコマンド。$PPIDがなんのpidなのかわからないがおそらくシェルのだろう。どっか他のコードでとってるんじゃないですかね。まあ見てみよう。

$  ps
  PID TTY          TIME CMD
20316 pts/5    00:00:01 xonsh
21745 pts/5    00:00:00 ps

$  cat /proc/20316/cmdline                                                          
/home/tia/.pyenv/versions/3.8.1/bin/python3.8-u/home/tia/.pyenv/versions/3.8.1/bin/xonsh--login

はい。まあ予想通りですね。と思ったけどなんか変だ。python3.8-u???なにこれと思ったけど右の方を見て察した。スペースが抜けてる。
なんでだろ。まあいいか。

xonshは直接xonshのバイナリを起動してるんじゃなくてpythonを起動してる。いやそれはそう。当たり前やん。

ですがまあ、なんとなく原因がわかりましたね。screenfetchはシェルを起動してるコマンドを取得してシェルの名前を取り出しているので、直接シェルじゃなくてpythonを起動しているxonshはxonshじゃなくてpythonと見られてしまう。

ついでにtrコマンドとheadコマンドを見てみよう。僕がしらないので。

...ggりタイム...

trは文字の入れ替え。str.replace()echo hoge | tr 'hoge' 'fuga''hoge'.replace('hoge', 'fuga')って意味。pythonで言うと

headは指定行の取り出し。str.splitlines(False)[n]echo "hoge\nfuga" | head -1'hoge\nfuga'.splitlines(False)[0]って意味。

で、cmdlineの中身をtr '\0' '\n'してる。うーん、あ、さっきスペースが抜けてるって思ったところ、スペースじゃなくて\0が入ってるのかも知れない。まあ実際打ってみればわかるか。

$  tr '\0' '\n'  < /proc/20316/cmdline
/home/tia/.pyenv/versions/3.8.1/bin/python3.8
-u
/home/tia/.pyenv/versions/3.8.1/bin/xonsh
--login

おっけい。多分それっぽい。ちゃんと改行されてる。

そして、これにhead -1してるので、1行目を取り出している。つまり、/home/tia/.pyenv/versions/3.8.1/bin/python3.8
完全にこれだ。

で、最後に

shell_type=${shell_type/-}
shell_type=${shell_type//*\/}

。多分/の一番右を取り出してるんだろう。

これでシェル_タイプがわかりましたね。

さて、後半。


detectshell () {

        ......

    case $shell_type in
        bash)
            shell_version_data=$( detectshell_ver "$shell_type" "^GNU.bash,.version" "4" )
            ;;
        BusyBox)
            shell_version_data=$( busybox | head -n1 | cut -d ' ' -f2 )
            ;;
        csh)
            shell_version_data=$( detectshell_ver "$shell_type" "$shell_type" "3" )
            ;;
        dash)
            shell_version_data=$( detectshell_ver "$shell_type" "$shell_type" "3" )
            ;;
        ksh)
            shell_version_data=$( detectshell_ver "$shell_type" "version" "5" )
            ;;
        tcsh)
            shell_version_data=$( detectshell_ver "$shell_type" "^tcsh" "2" )
            ;;
        zsh)
            shell_version_data=$( detectshell_ver "$shell_type" "^zsh" "2" )
            ;;
        fish)
            shell_version_data=$( fish --version | awk '{print $3}' )
            ;;
    esac

    if [[ -n $shell_version_data ]];then
        shell_type="$shell_type $shell_version_data"
    fi

    myShell=${shell_type}
    verboseOut "Finding current shell...found as '$myShell'"
}

これは・・・・・・完全無視だ。$shell_typebash, BusyBox, csh, dash, ksh, tcsh, zsh, fishのどれかならバージョンを読むっぽい。無視無視。

さあて、結論が出ました。

xonshはbashとかのようにbashと直接呼び出しているわけでなくpython xonshとpythonの上に動いているので、直接呼び出されているpytohnがシェルとして検出される。以上。

対策

detectshell()の一行目を見てみましょう。

detectshell () {
    if [[ ! "${shell_type}" ]]; then
...

そう、最初に既に$shell_typeが設定してあるか見てるのだ。つまり対策としては

$ $shell_type = $(xonsh -V).strip()
$ screenfetch

以上!

           /:-------------:\          user@host
        :-------------------::        OS: Fedora 30 Thirty
      :-----------/shhOHbmp---:\      Kernel: x86_64 Linux 5.3.16-200.fc30.x86_64
    /-----------omMMMNNNMMD  ---:     Uptime: 14h 28m
   :-----------sMMMMNMNMP.    ---:    Packages: 2531
  :-----------:MMMdP-------    ---\   Shell: xonsh/0.9.13.dev1
 ,------------:MMMd--------    ---:   Resolution: 1920x1080
 :------------:MMMd-------    .---:   DE: GNOME 
 :----    oNMMMMMMMMMNho     .----:   WM: GNOME Shell
 :--     .+shhhMMMmhhy++   .------/   WM Theme: Adwaita
 :-    -------:MMMd--------------:    GTK Theme: Adwaita [GTK2/3]
 :-   --------/MMMd-------------;     Icon Theme: Adwaita
 :-    ------/hMMMy------------:      Font: Cantarell 11
 :-- :dMNdhhdNMMNo------------;       CPU: Intel Core i7-8550U @ 8x 4GHz
 :---:sdNMMMMNds:------------:        GPU: Mesa DRI Intel(R) UHD Graphics 620 (Kabylake GT2) 
 :------:://:-------------::          RAM: 6954MiB / 15779MiB
 :---------------------://           

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0