質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Q&A

解決済

1回答

1394閲覧

【Shell】bashからkshに変更できない

katahik

総合スコア79

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

0グッド

0クリップ

投稿2023/03/24 11:02

編集2023/03/24 11:12

実現したいこと

Dockerでcentosのコンテナを作成しており、以下のDockerfile及びコマンドを使用して、シェルをkshに変更しようとしていますが、shになってしまっているように見えます。

期待する動作

echo ${SHELL} /bin/ksh

現状の動作

echo ${SHELL} /bin/sh

原因がわからず、解決策もわかりません。
なにかわかる方がいらっしゃれば教えていただけると幸いです。

該当のソースコード

Dockerfile

FROM centos:centos7 RUN yum install ksh -y RUN chsh -s /bin/ksh root CMD ["/bin/ksh"]

build

docker build -t mybashimage . [+] Building 33.5s (7/7) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 129B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/centos:centos7 0.0s => CACHED [1/3] FROM docker.io/library/centos:centos7 0.0s => [2/3] RUN yum install ksh -y 31.5s => [3/3] RUN chsh -s /bin/ksh root 0.4s => exporting to image 1.6s => => exporting layers 1.6s => => writing image sha256:ffefefa6641e2cb21bd90aec5b257c130ade5bb11d02cd7604d6a3c7baf2be10 0.0s => => naming to docker.io/library/mybashimage

コンテナ立ち上げ

docker run -it --rm mybashimage:latest

シェルの確認

# echo ${SHELL} /bin/sh

シェルが/bin/shとなっている

試したこと

ユーザー(root)のシェルが変わっているか=> rootのシェルは、/bin/kshに変わっていた

# head /etc/passwd root:x:0:0:root:/root:/bin/ksh bin:x:1:1:bin:/bin:/sbin/nologin

ログインユーザーの確認

# whoami root

shellsの確認

# cat /etc/shells /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash /bin/ksh /bin/rksh

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2023/03/24 14:03

psではどう表示されますか?
katahik

2023/03/24 15:03

コメントありがとうございます。 psしたときは、以下のようにkshが動いていたのを確認しました $ ps PID TTY TIME CMD 19 pts/0 00:00:00 ksh echo ${SHELL}したときのシェルが正しいものと信じていましたが、最新の正しい情報とは限らないのですね。
katahik

2023/03/24 15:04

また、rootではなく、useraddでユーザーを追加して、そのユーザーのシェルを変えたら、echo ${SHELL}で/bin/kshと表示がされていました
guest

回答1

0

ベストアンサー

man kshではよくわからないので、普通のLinuxOS(非Docker)にkshをインストールしてみましたが、/bin/kshをログインシェルにするとSHELL/bin/kshになりました。

ログイン時に環境変数SHELLを設定するのは、シェルではなくて、/bin/login等のログインプロセスです。
シェル自体は環境変数SHELLが定義されていれば変更しません(下記※参照)。

なので、/etc/passwd/bin/kshであれば、ログイン処理が行われれば、ログインプロセスが環境変数SHELLに/bin/kshを設定するはずです。
質問にはシェルをどうやって起動したかが書かれていませんが、docker exec -it CONTAINER /bin/ksh等ではログイン処理をするわけではなく単にkshコマンドを起動するだけでしょう。

環境変数SHELLが未定義の場合は、下記のように/bin/shが設定されるみたいなので、やはり未設定のままでkshが起動されていると思われます。

sh

1$ env -u SHELL ksh -c 'echo $SHELL' 2/bin/sh

何故/bin/kshでなく/bin/shが設定されるのかはman kshからは不明です。/bin/sh上位互換として作られたからですかね。

参考

※ もちろん、変更しないと言っても、bashrc zshrc kshrc等でSHELLを変更するように書かれていればそれが実行されて上書きします。手元の/etc/bashrcにはSHELL=/bin/bashと書かれていますので、対話型でbashを起動すると上書きされます。

sh

1$ SHELL=/bin/ksh bash -c 'echo $SHELL' 2/bin/ksh # bash -c では /etc/bashrcは読まないので不変 3$ SHELL=/bin/ksh bash -ic 'echo $SHELL' 4/bin/bash # bash -ic だと /etc/bashrcを読むので上書き

投稿2023/03/24 17:59

編集2023/03/24 18:10
otn

総合スコア84555

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dameo

2023/03/24 19:08 編集

起動方法は書かれていたし、再現もしましたよ。 一般ユーザーだけSHELLがkshを指すようになり、rootについては確かに/bin/shのままでしたね。 また/etc/*にはSHELLという記述がbashrc以外になく、root/一般ユーザのdotfilesにもSHELLの記述はないようでした。 元来SHELL環境変数は実行中のshellには関係ないようですが(posix)。。。この辺のルールはよく分かりませんでした。
katahik

2023/03/24 20:29

なるほど、ありがとうございます /etc/passwdが/bin/kshであれば、ログインプロセスが環境変数SHELLに/bin/kshを設定するはずということですかね? ということは、 現在、rootではなく別ユーザーを作成して、環境変数SHELLの中身が/bin/kshであることを確認しました。なので、kshが起動していると認識ですがあってますか?
dameo

2023/03/25 05:59 編集

loginプロセスと言っているのが、kshの中の起動処理を指しているのか(.kshrc)と思っていましたが、OSのログインプロセス(/bin/login)を指していたのですね。それなら説明のとおりだと思います。 su -とかlogin -f rootなどなら/proc/[pid]/cmdlineが-kshとなり、kshがログインシェルとして起動した場合だけSHELL変数が/bin/kshとなっていました。 一般ユーザーとしてkshを起動したときはsu -で起動していたため、kshがログインシェルになっていて、同様の状況になっていました。 ただしユーザーは関係なく、/proc/pid/cmdlineを再現するexec -a -ksh /bin/kshなどとした場合も、echo $SHELLは/bin/kshのままになっており、kshでの設定ではなく、/bin/loginの設定だと考えられます。 kshをログインシェルとして起動しない場合に、SHELL変数が設定されていたのは、kshのデフォルトとして/bin/shが埋め込まれていたからで(srpmで確認)、これも説明のとおりでしたよ。 以下確認用 $ docker run -it --rm mybashimage su - # echo $SHELL /bin/ksh # exit $ docker run -it --rm mybashimage login -f root # echo $SHELL /bin/ksh # exit $ docker run -it --rm mybashimage ksh -c 'adduser hoge;chsh -s /bin/ksh hoge;su - hoge' Changing shell for hoge. Shell changed. $ echo $SHELL /bin/ksh $ exit $ docker run -it --rm mybashimage ksh -c 'adduser hoge;chsh -s /bin/ksh hoge;login -f hoge' Changing shell for hoge. Shell changed. $ echo $SHELL /bin/ksh $ exit $ docker run -it --rm mybashimage su - # set -o emacs # yumdownloader --source ksh ... # rpm -ivh ksh-20120801-144.el7_9.src.rpm ... # cd rpmbuild/SPECS/ # yum install -y rpm-build bison ... # rpmbuild -bp ksh.spec ← ココまででソースは読める形に展開される ... # yum install -y gcc ... # rpmbuild -bc ksh.spec ← ココまででソースはビルドされる(rpm作ったりとかしない) ... # gdb /root/rpmbuild/BUILD/ksh-20120801/arch/linux.i386-64/bin/ksh ... (gdb) b init.c:1986 Breakpoint 1 at 0x41f38e: file /root/rpmbuild/BUILD/ksh-20120801/src/cmd/ksh93/sh/init.c, line 1986. (gdb) r ... (gdb) l 1981 np->nvalue.bfp = (Nambfp_f)((struct shtable3*)tp)->sh_value; 1982 else 1983 { 1984 if(name_vals == shtab_variables) 1985 np->nvfun = &shp->nvfun; 1986 np->nvalue.cp = (char*)tp->sh_value; 1987 } 1988 nv_setattr(np,tp->sh_number); 1989 if(nv_isattr(np,NV_TABLE)) 1990 nv_mount(np,(const char*)0,dict=dtopen(&_Nvdisc,Dtoset)); (gdb) display *tp 1: *tp = {sh_name = 0x53ea4a "PATH", sh_number = 0, sh_value = 0x0}(gdb) c ... (gdb) c ...(tp->nvnameが"SHELL"になるまで繰り返す) Continuing. Breakpoint 1, inittree (shp=shp@entry=0x770000 <sh>, name_vals=0x5138e0 <shtab_variables>) at /root/rpmbuild/BUILD/ksh-20120801/src/cmd/ksh93/sh/init.c:1986 1986 np->nvalue.cp = (char*)tp->sh_value; 1: *tp = {sh_name = 0x53e42e "SHELL", sh_number = 512, sh_value = 0x51361a "/bin/sh"} →確かに環境変数の初期値に入っている (gdb) up #1 0x0000000000420448 in nv_init (shp=0x770000 <sh>) at /root/rpmbuild/BUILD/ksh-20120801/src/cmd/ksh93/sh/init.c:1830 1830 shp->var_base = shp->var_tree = inittree(shp,shtab_variables); (gdb) l 1825 if(!ip) 1826 return(0); 1827 shp->nvfun.last = (char*)shp; 1828 shp->nvfun.nofree = 1; 1829 ip->sh = shp; 1830 shp->var_base = shp->var_tree = inittree(shp,shtab_variables); 1831 SHLVL->nvalue.ip = &shlvl; 1832 ip->IFS_init.hdr.disc = &IFS_disc; 1833 ip->PATH_init.disc = &RESTRICTED_disc; 1834 ip->PATH_init.nofree = 1; (gdb) l /root/rpmbuild/BUILD/ksh-20120801/src/cmd/ksh93/data/variables.c:37,47 ← 定義はココ 37 const struct shtable2 shtab_variables[] = 38 { 39 "PATH", 0, (char*)0, 40 "PS1", 0, (char*)0, 41 "PS2", NV_NOFREE, "> ", 42 "IFS", NV_NOFREE, " \t\n", 43 "PWD", 0, (char*)0, 44 "HOME", 0, (char*)0, 45 "MAIL", 0, (char*)0, 46 "REPLY", 0, (char*)0, 47 "SHELL", NV_NOFREE, "/bin/" SH_STD, (gdb) q ... Quit anyway? (y or n) y # exit $
dameo

2023/03/25 08:20

これは言わなくても分かるかとも思ったけどいろんな人が読むかもしれないので、一応ちゃんと書いておくと、この値はSHELL変数が設定されてると、以下の関数で上書きされます(/root/rpmbuild/BUILD/ksh-20120801/src/cmd/ksh93/sh/init.c)。 void env_init(Shell_t *shp)
katahik

2023/03/25 09:18

詳細な検証ありがとうございます。kshがログインシェルではなかったため、環境変数SHELLに入っていなかったのですね。理解しました。ありがとうございましt。
otn

2023/03/25 15:49

> kshがログインシェルではなかったため、環境変数SHELLに入っていなかった 「/bin/login等のログイン処理を経ずにkshを起動したため」ですね。
otn

2023/03/25 16:00

> loginプロセスと言っているのが、kshの中の起動処理を指しているのか(.kshrc)と思っていましたが、 そこは、「シェルではなくて、/bin/login等のログインプロセスです。」の部分で説明したつもりでした。 最初、「シェルではなくて、/bin/login等のログイン処理コマンドです。」と書きかけてたのですが、xdmのようなGUIログインを処理する物を「コマンド」と言っていいのか迷って「プロセス」と書いたのですが、「ログインプロセス」単独で見ると、「OSプロセス」的な意味じゃなくて「過程」の意味の「プロセス」とも取れますね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問