

nologinユーザーにsuするなら-sでシェルを指定する
この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。
Webサーバーの実行ユーザー(apache など)の権限でファイルが読めるか確認したくて、su しようとしたら弾かれた。原因と回避方法をまとめておく。
何が起きたか
まず /etc/passwd で apache ユーザーを確認する。
# grep apache /etc/passwdapache:x:48:48:Apache:/var/www:/sbin/nologinログインシェルは /sbin/nologin になっている。この状態で普通に su してみる。
# su - apacheThis account is currently not available.これで終了してしまう。
なぜ弾かれるのか
su は切り替え先ユーザーのログインシェル、つまり /etc/passwd の最後のフィールドを起動する。apache の場合は /sbin/nologin が起動する。nologin は「This account is currently not available.」と出力して終了するだけのプログラムなので、シェルに入れない。
サービス用のユーザーは対話ログインさせないのが前提なので、この挙動は意図どおりになる。
flowchart TD
A["su - apache"] --> B["/etc/passwd のシェルを参照"]
B --> C["/sbin/nologin を起動"]
C --> D["メッセージを出して終了"]
E["su -s /bin/bash apache"] --> F["-s で指定したシェルを使用"]
F --> G["/bin/bash が apache 権限で起動"]
-sでシェルを上書きする
su の -s(--shell)で、起動するシェルを指定できる。/etc/passwd のシェルよりこちらが優先される。
# su -s /bin/bash apachebash-4.1$ iduid=48(apache) gid=48(apache) 所属グループ=48(apache)bash-4.1$ pwd/rootこれで apache の権限で bash が動く。ただし、カレントディレクトリは /root のままになる。
- を付けるとログインシェルになる
-(-l / --login)を付けると、ログインシェルとして起動する。
# su -s /bin/bash - apache-bash-4.1$ iduid=48(apache) gid=48(apache) 所属グループ=48(apache)-bash-4.1$ pwd/var/www違いは次のとおり。
su -s /bin/bash apache |
su -s /bin/bash - apache |
|
|---|---|---|
| シェルの種類 | 非ログインシェル | ログインシェル |
| カレントディレクトリ | 元のまま(/root) |
ホームディレクトリ(/var/www) |
| 環境変数 | 元のユーザーのものが一部残る | 切り替え先ユーザーの環境で初期化 |
| プロンプト | bash-4.1$ |
-bash-4.1$ |
プロンプト先頭の - は、ログインシェルとして起動したことを表している($0 が -bash になる)。
権限の確認が目的なら、- を付けるほうがいい。root の PATH などが残っていると、確認結果が本番の挙動とずれる可能性がある。
オプションの順番
man には、- は su のオプションの最後に置くよう書かれている。そのため su -s /bin/bash - apache の順番で書くのが正しい。順番を気にしたくないなら、-l を使えばどこに置いてもいい。
# su -l -s /bin/bash apacheコマンドを1つだけ実行する
シェルに入らずにコマンドを1つだけ実行したいなら、-c を使う。
# su -s /bin/bash -c 'ls -l /var/www/html' apachesudoでやる場合
sudo でも同じことができる。
# sudo -u apache /bin/bashsudo -u apache -i は、切り替え先ユーザーのログインシェルを起動するので、su - apache と同じく nologin に弾かれる。
RHEL 系なら runuser も使える(root 専用)。
# runuser -s /bin/bash - apache注意点
apacheにはパスワードが設定されていないので、この方法が使えるのは root からだけになる。- 対話ログインを防ぐための設定なので、
/etc/passwdのシェルを書き換えて解決するのは避ける。一時的に入りたいだけなら、-sで十分。 - 上の出力は bash 4.1(CentOS 6 世代)の環境で取ったもの。
suの基本的な挙動は他のディストリビューションでも同じはずだけど、環境変数の引き継ぎ方はsuの実装(coreutils / util-linux)によって細かく違う。