21
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

シェルスクリプトの中で現在利用しているシェルを確認する方法

Last updated at Posted at 2021-07-10

みなさん、シェル使ってますか?私は毎日使ってます。
「シェルとは?」といった記事はたくさんあるのでここでは深く触れませんが、ざっくり言うと「コマンドでカーネルと対話的なインターフェースを提供する仕組み」といった感じでしょうか。
そんなシェルについてですが、「シェルスクリプトの中で現在利用しているシェルを確認する方法」が知りたくてちょっと調べてみました。


今回の動作確認環境

  • Vagrant 2.2.14
  • CentOS 8

※Dockerを利用すると $SHELL (ログインシェル(デフォルトシェル))の表示の際に期待した動作とは異なりました。Dockerの場合は動作に必要な最小構成になっていることがあったり、ホストPC上で動作している仕組みのためにこのようなことが起こるのかもしれません。そういったことを踏まえて今回はVagrantを使ってみてます。(このあたりは詳しく調べきれてないところではあります)


「LinuCレベル1」の試験範囲に「GNUとUnixのコマンド」という章があり、試験勉強をしているとその中で以下のコマンドで「現在のシェル」を知ることができると説明されています。

$ echo $SHELL
/bin/bash

完。。。

と思うじゃないですか。
でも、この $SHELL は想定とは違う動きをします。

↑のコマンドはCentOS8の環境で実行したんですが、CentOS8の初期状態は利用できるシェルが少ない状態です。
以下のコマンドで確認すると shbash のみです。

$ cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash

しかも shbash へのシンボリックリンクになっているので実質1種類と言えます。

$ ls -l /usr/bin/sh
lrwxrwxrwx. 1 root root 4 May 11  2019 /usr/bin/sh -> bash
$ ls -l /bin/sh
lrwxrwxrwx. 1 root root 4 May 11  2019 /bin/sh -> bash

なので、 zshkshtcsh をインストールします。

$ sudo yum install zsh ksh tcsh -y

このように利用可能なシェルが増えました。

$ cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/usr/bin/zsh
/bin/zsh
/bin/csh
/bin/tcsh
/usr/bin/csh
/usr/bin/tcsh
/bin/ksh
/bin/rksh
/usr/bin/ksh
/usr/bin/rksh

それでは改めて $SHELL を見てみましょう。

zsh に変更して。。。おや?

$ zsh
% echo $SHELL
/bin/bash

ksh に変更して。。。おやおや?

$ ksh
$ echo $SHELL
/bin/bash

tcsh に変更して。。。おやおやおや?

$ tcsh
$ echo $SHELL
/bin/bash

期待している動作と異なりますね。
$SHELL は現在のシェルではなく、どうやらログインシェル(デフォルトシェル)を表示しているようです。
こういった場合に使えるのが $0 です。

ログイン直後でデフォルトシェルが bash の場合は。

$ echo $0
-bash

zsh に変更すると。

$ zsh
% echo $0
zsh

ksh に変更すると。

$ ksh
$ echo $0 
ksh

tcsh に変更すると。

$ tcsh 
$ echo $0
tcsh

完。。。といった感じですね。


それではタイトルのとおり、「シェルスクリプトの中で現在利用しているシェル」を確認していこうと思います。

まずは $0 を表示するスクリプトを記述したファイルを作成します。

$ echo 'echo $0' > show_shell.sh

それでは bash で実行してみます。

$ bash show_shell.sh 
show_shell.sh

ファイル名が表示されました。
そりゃそうです。 man bash を開くと ARGUMENTS のところに $0 is set to the name of the file と明記されています。
ついこの前書いた「bashの特殊変数の説明を読んでもよくわからなかったので試してみた」という記事の中でも、 $0 は「スクリプトファイル名」と説明していますし。。。

困りましたね。どのシェルで呼び出してもすべて同じ結果です。

$ zsh show_shell.sh 
show_shell.sh
$ ksh show_shell.sh 
show_shell.sh
$ tcsh show_shell.sh 
show_shell.sh

そこで登場するのが /proc ディレクトリです。
/proc 配下のファイルには色々な情報が詰まっている特別なディレクトリで、 /proc/cpuinfo/proc/meminfo なんかは利用したことがあるんじゃないでしょうか。
/proc 配下のファイルは通常のファイルとは異なる形式になっていて、ファイルサイズが0だったり、作成日時が現在時刻だったりと不思議な作りになっています。

$ ls -l /proc/cpuinfo
-r--r--r--. 1 root root 0 Jul  9 16:56 /proc/cpuinfo
$ ls -l /proc/meminfo
-r--r--r--. 1 root root 0 Jul  9 16:56 /proc/meminfo

/proc 配下のファイルを見てみると、数字のディレクトリが存在しています。これはプロセスIDと一致しています。

$ ls /proc/
1    1902   25   441  636  725        execdomains  loadavg       softirqs
10   2      26   442  637  8          fb           locks         stat
11   20     27   443  656  9          filesystems  mdstat        swaps
12   21     28   444  659  acpi       fs           meminfo       sys
13   22     29   445  661  asound     interrupts   misc          sysrq-trigger
14   23     3    446  662  buddyinfo  iomem        modules       sysvipc
141  24     30   447  663  bus        ioports      mounts        thread-self
142  24687  31   448  666  cgroups    irq          mtrr          timer_list
143  24697  32   48   667  cmdline    kallsyms     net           tty
144  24701  4    535  689  consoles   kcore        pagetypeinfo  uptime
146  24705  416  561  691  cpuinfo    key-users    partitions    version
147  24711  418  6    692  crypto     keys         sched_debug   vmallocinfo
16   24712  420  619  699  devices    kmsg         schedstat     vmstat
17   24844  421  624  711  diskstats  kpagecgroup  scsi          zoneinfo
18   24874  422  625  715  dma        kpagecount   self
19   24882  440  635  724  driver     kpageflags   slabinfo

bashの特殊変数の説明を読んでもよくわからなかったので試してみた」の中で「現在実行しているシェルのPID」は $$ で表現されると説明しました。
これを応用して、 ls /proc/$$ を実行してみましょう。すると現在のプロセスIDで動いている固有の情報が詰まったファイルの一覧が表示されます。

$ ls /proc/$$
attr                cpuset   loginuid    numa_maps      sched         status
autogroup           cwd      map_files   oom_adj        schedstat     syscall
auxv                environ  maps        oom_score      sessionid     task
cgroup              exe      mem         oom_score_adj  setgroups     timens_offsets
clear_refs          fd       mountinfo   pagemap        smaps         timers
cmdline             fdinfo   mounts      patch_state    smaps_rollup  timerslack_ns
comm                gid_map  mountstats  personality    stack         uid_map
coredump_filter     io       net         projid_map     stat          wchan
cpu_resctrl_groups  limits   ns          root           statm

この中で注目すべきファイルは exe です。
man proc を見てみると、 /proc/[pid]/exethis file is a symbolic link containing the actual pathname of the executed command. のように説明されています。

「実行されたコマンドの実際のパス名を含んだファイル」ということは、 /proc/$$/exels してみると。。。現在実行しているシェルへのシンボリックリンクが表示されました!

$ ls -l /proc/$$/exe
lrwxrwxrwx. 1 vagrant vagrant 0 Jul  9 17:13 /proc/24712/exe -> /usr/bin/bash

シンボリックリンクのリンク先の名前を表示する readlink というコマンドを組み合わせると。。。来ました!これが求めていたものです!!

$ readlink /proc/$$/exe
/usr/bin/bash

事前に準備していた show_shell.sh を書き換えます。

$ echo 'readlink /proc/$$/exe' > show_shell.sh

それぞれのシェルで実行してみると、「シェルスクリプトの中で現在利用しているシェル」を表示することができました。

$ bash show_shell.sh
/usr/bin/bash
$ ksh show_shell.sh
/usr/bin/ksh93
$ zsh show_shell.sh
/usr/bin/zsh
$ tcsh show_shell.sh
/usr/bin/tcsh

この /proc/$$/exeshebang にも有効です。
実行可能なファイルの場合、シェルスクリプトは shebang を元にどのシェルを利用するのかを決定するので、 show_shell.sh 次のように書き換えて試してみます。

実行権限を付与しておいて。

$ chmod +x show_shell.sh

まずは bash の場合。このように shebang を書いて。

$ cat show_shell.sh
#!/usr/bin/bash
readlink /proc/$$/exe

実行。

$ ./show_shell.sh 
/usr/bin/bash

zsh の場合も同様に shebang を書き換えて。

$ cat show_shell.sh
#!/usr/bin/zsh
readlink /proc/$$/exe

実行。

$ ./show_shell.sh 
/usr/bin/zsh

ここで、さらに実験です。実行可能なファイルで shebang が書かれていない場合はどうなるのでしょうか。

$ cat show_shell.sh
readlink /proc/$$/exe

CentOS8の場合は /usr/bin/bash が選択されました。

$ ./show_shell.sh 
/usr/bin/bash

shebang が無い場合の実行可能ファイルのシェルの決定ロジックについては複雑なようで、「実行可能ファイルの場合はどのシェルが利用されるかわからないような曖昧な状態にせず shebang を書いて意図どおりのシェルが選択されるようにしましょう」ということみたいですね。

参考URL

21
21
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
21
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?