Linux / コマンド / su - ユーザーアカウントの切り替え

suは、代替ユーザーおよびグループIDでシェルまたはコマンドを実行するツールです。ユーザーを指定しない場合、通常rootを対象とし、su --login ユーザーを使用すると、そのユーザーが直接ログインしたのと似た環境に切り替えることができます。

単純なsu ユーザーは、現在の作業ディレクトリや一部の環境を維持するため、異なるユーザーの設定が混ざる可能性があります。対話式のアカウント切り替えには通常su --login ユーザーを使用し、管理者コマンドのみを実行する目的であれば、ポリシーベースのsudoの方が適しているかを事前に確認するのがよいでしょう。

suコマンドとは?

suは、substitute user and group ID、すなわち代替ユーザーおよびグループIDでコマンドを実行します。ユーザー名を省略すると、rootアカウントで対話式シェルを実行しようとします。

util-linuxのsuは、PAM(Pluggable Authentication Modules)を通じて認証、アカウントおよびセッション管理を行います。どのパスワードが必要か、特定のグループだけがsuを使用できるか、試行内容がどこに記録されるかは、ディストリビューションのPAMとセキュリティ設定によって異なる場合があります。

この記事は、Linuxで広く使用されているutil-linuxの実装を基準としています。su --versionとsu --helpで実装と対応オプションを確認してください。例中のdeploy・backupは実在する対象アカウントに置き換えます。/usr/local/bin/check-jobや/usr/local/bin/backup-jobは、あらかじめ用意したジョブのパスを表す例です。存在しない場合は実行可能なidの例から確認してください。正確な動作やシステムごとの設定ファイルは、util-linux su 公式マニュアルページで確認できます。

基本の文法とアカウントの切り替え

基本的な文法は次の通りです。

su [オプション] [-] [ユーザー [引数...]]

ユーザーを指定しない場合、rootアカウントに切り替えを試みます。

su

一般ユーザーが実行すると、通常は対象であるrootアカウントのパスワードを求められます。rootアカウントがロックされている場合やPAMポリシーで許可されていない場合、正しいユーザーパスワードを知っていても切り替えることはできません。

特定のユーザーに切り替えるには、アカウント名を指定します。

su deploy

元のシェルに戻るには、切り替えたシェルで exit を実行するか、Ctrl+D を入力します。

exit

su と su --login の違い

区分 su ユーザー su --login ユーザー
作業ディレクトリ 現在のディレクトリを維持 対象ユーザーのホームディレクトリに移動
環境変数 一部のみ変更され、既存の環境と混ざる可能性あり ほとんど削除し、対象ユーザーのログイン環境を構成
PATH システム設定とPAMの影響を受ける 対象ログイン環境に合わせて初期化
シェルの起動方式 一般対話型シェル ログインシェルとして起動
推奨状況 環境を維持することを意図した制限的な場合 一般的な対話型ユーザー切り替え

util-linuxマニュアルは、環境の混在による副作用を避けるために--loginの使用を推奨しています。短い形式である-も同じ意味です。

su --login deploy
su - deploy

ログインシェルで変わる環境

ほとんどの既存の環境変数を整理する

util-linuxのsu --loginは、TERM、COLORTERM、NO_COLORと、--whitelist-environmentで明示的に許可した変数を除き、既存の環境を消去します。その後、HOME、SHELL、USER、LOGNAME、PATHを対象ユーザー基準で初期化します。

最終環境にはPAMモジュールが追加または変更した値も反映される可能性があるため、ディストリビューションごとに完全に同じであるとは考えないでください。

対象ユーザーのホームディレクトリに移動する

--loginは対象ユーザーのホームディレクトリに移動した後、ログインシェルを開始します。移行後は次のコマンドでユーザー・ホーム・作業ディレクトリを確認できます。

id
printf '%s\n' "$HOME"
pwd

シェル初期化ファイルが変わる

ログインシェルは使用するシェルの規則に従ってログイン用初期化ファイルを読み込みます。Bashであれば、システムとユーザー設定に従って/etc/profile、~/.bash_profileなどの影響を受ける可能性があります。実際の順序は対象シェルのマニュアルおよび該当アカウントの設定を確認してください。

よく使うsuオプション

オプション 機能 活用と注意点
-, -l, --login ログインシェル環境に切り替え 対話モード切り替えが一般的に推奨される
-c コマンド, --command コマンド シェルに単一のコマンドを渡す 引用符と終了ステータスを確認する必要がある
-s シェル, --shell シェル 実行するシェルを指定 制限付きシェルアカウントでは呼び出し元が root でない場合、無視されることがある
-m, -p, --preserve-environment 現在の環境をできるだけ保持 --login と共に使用すると無視され、セキュリティ上注意して使用すること
-w リスト, --whitelist-environment リスト ログイン切り替え時に指定された環境変数を保持 カンマで区切り、主要アカウント変数は除外
-P, --pty セッションに別の擬似端末を作成 対話型セッションで端末を分離するのに便利
-g グループ プライマリグループを指定 rootユーザーのみ使用可能
-G グループ 補助グループを指定 rootユーザーのみ使用可能で、繰り返し可能

別のユーザーとして単一コマンドを実行する

-cでコマンドをひとつ実行する

対話型シェルに留まる必要がなければ-cで対象ユーザーのシェルにコマンドを渡すことができます。

su -c 'id' deploy

コマンドが終了するとsuも終了し、元のシェルに戻ります。コマンド文字列は対象シェルで再解釈されるため、引用符、変数展開やリダイレクトの実行タイミングに注意してください。

ログイン環境でコマンドを実行する

対象ユーザーのログイン環境とホームディレクトリでコマンドを実行するには--loginを併用します。

su --login -c 'pwd; id' deploy

セミコロンでつながれた二つのコマンドも対象ユーザーのシェル内で実行されます。外部入力をコマンド文字列に直接結合するとコマンドインジェクションのリスクがあるため、動的に作成した文字列を高権限で渡さないでください。

コマンドの終了状態を確認する

suは一般的に実行したコマンドの終了状態を返します。util-linuxの実装では、コマンドを実行できない場合は126、コマンドが見つからない場合は127、コマンド実行前の一般的なエラーは1を返すことがあります。

su -c '/usr/local/bin/check-job' deploy
status=$?
printf 'exit=%s\n' "$status"

自動化では出力文字列だけでなく、終了状態も確認する必要があります。

シェルと制限アカウントの扱い

対象ユーザーのデフォルトシェル

特別なオプションがなければ、通常は対象アカウントのpasswdエントリに指定されたシェルを使用し、なければ/bin/shで代替します。アカウント情報を確認する際は、全体の/etc/passwdを任意に変更せず、次のように照会します。

getent passwd deploy

-sでシェルを指定する

-sで別のシェルを指定できます。

su -s /bin/sh -c 'id' deploy

対象アカウントのシェルが/etc/shellsにない制限シェルである場合、一般ユーザーが指定したシェルは無視されることがあります。rootが制限を回避できるからといって、サービスアカウントに対話型シェルを開いても安全であるとは限りません。

サービスアカウントの目的を尊重する

nologinやfalseがシェルに指定されているアカウントは、対話型ログイン用ではない可能性が高いです。そのアカウントで作業する必要がある場合は、必要なコマンドのみを実行し、サービスが提供する管理コマンドやsystemdの機能があるかどうかをまず確認してください。

環境変数の保持は慎重に使用する

--preserve-environmentの意味

--preserve-environmentは、HOME、SHELL、USER、LOGNAMEを新たに設定せず、現在の環境を保持します。--loginと一緒に指定すると無視されます。

su --preserve-environment deploy

呼び出しユーザーの設定をそのまま渡す特別な場合でない限り、対象アカウントのホームと実行環境が混ざり、予期しないファイル所有権や設定変更が発生する可能性があります。

必要な変数のみ許可する

util-linuxでは--loginと--whitelist-environmentを組み合わせて、必要な変数のみ保持できます。

su --login --whitelist-environment=LANG,LC_ALL deploy

HOME、SHELL、USER、LOGNAME、PATHはホワイトリストの対象から除外されます。ロケール変数もプログラムの動作に影響を与える可能性があるため、必要な値のみを渡してください。

suとsudoの違い

区分 su sudo
主な目的 別のユーザーとしてシェルまたはコマンドを実行 ポリシーが許可したコマンドを別のユーザーで実行
一般的な認証 対象ユーザーのパスワード 呼び出しユーザーのパスワード
権限の範囲 切り替えたシェルで対象アカウントの権限を引き続き使用可能 許可されたコマンドと条件で制限可能
監査と追跡 セッション切り替えの記録中心で、内部コマンドの追跡は別途必要 実行要求をポリシー・ロギングプラグインで記録可能
適した状況 対象アカウントの対話型環境が必要な場合 管理コマンド1つまたは役割別最小権限の実行

認証方式とロギングはPAMとポリシーによって異なる場合があるため、上の表は一般的な比較です。rootコマンド1つだけが必要な場合は、アカウントパスワードを共有するsuより、権限をコマンド別に制限できるsudoの方が適していることが多いです。詳しい使用方法はLinux sudoコマンドとsudoers設定を参照してください。

rootアカウントに切り替えられない理由

rootアカウントがロックされている可能性がある

一部のディストリビューションでは、rootアカウントのパスワードによるログインをデフォルトで無効にし、sudoによる管理方法を使用しています。この場合、su -で現在のユーザーのパスワードを入力しても成功しません。

ユーザーがsudo権限を持ち、ポリシーが許可している場合、ログイン形式のrootシェルを次のように開くことができますが、個別のコマンドだけが必要な場合は、管理者シェルよりもsudo コマンドを使用するほうが安全です。

sudo -i

PAMまたはグループポリシーで制限される可能性がある

/etc/pam.d/suのポリシーは、特定のグループだけがsuを使用できるように制限したり、追加の認証条件を適用することがあります。権限を取得するためにPAM設定を任意に緩めず、システム管理者に必要な作業と対象アカウントを伝えてください。

対象アカウントの状態に問題がある可能性がある

アカウントの期限切れ、ロック、ホームディレクトリの誤り、制限されたシェルやファイル権限によって切り替えが失敗することがあります。管理者であれば、getent passwd ユーザー、アカウント管理ツールおよび認証ログを通じて原因を確認してください。

rootが他のユーザーとして実行する場合

自動化には runuser の方が適している場合があります

util-linux のマニュアルでは、すでに高い権限を持つプロセスや root のスクリプトで他のユーザーとして実行する際に runuser を推奨しています。runuser は set-user-ID ではなく、パスワード認証を要求せず、別の PAM 構成を使用します。

runuser -u backup -- /usr/local/bin/backup-job

runuser は root が使用する管理ツールであるため、一般ユーザーが sudo の代わりに権限を取得するコマンドではありません。

PAM セッションが不要な場合は目的を再検討してください

単にユーザー・グループ ID と権限属性を変更してプログラムを実行する必要があり、PAM セッションが不要な場合、util-linux は setpriv も代替案として案内しています。このツールは権限とセキュリティ属性を直接扱うため、正確なユーザー・グループ・補助グループ・ケーパビリティ(プロセスに与える個別の特権)の設定を理解している管理者のみが使用すべきです。

擬似端末でセッションを分離する

--pty が提供する分離

--ptyは、もともとのセッションと対象のセッションの間に別の擬似端末を作成し、suが入出力を中継します。対話型セッションで、両方のセッションが同じ端末を直接共有しないようにすることで、セキュリティを向上させることができます。

su --pty --login deploy

完全な systemd ログインセッションではありません。

su --loginを使用しても、systemd-logind の観点から完全に新しい実際のログインセッションを作ることにはなりません。ユーザーサービス、シート、セッション境界が必要な作業の場合は、systemd-runやmachinectlのように目的に応じたツールを検討する必要があります。

セキュリティ上の注意点

  • rootパスワードや他のユーザーのパスワードを複数人と共有しないようにします。
  • パスワードをコマンドライン、シェル履歴、スクリプト、パイプに入れないようにします。
  • 不必要にrootシェルを長く維持せず、作業後は直ちにexitします。
  • 切り替え直後にid、pwd、HOMEを確認し、ユーザーやパスを間違えないようにします。
  • 高い権限で実行するコマンドは、オプション、対象パスとワイルドカード展開結果をまず確認します。
  • ログが残ると仮定せず、PAM・ジャーナル・認証ログの実際の設定と保存ポリシーを確認します。

suでrootシェルを開いた後に実行した各コマンドはsu自体の認証記録とは別です。個別コマンドの監査が必要な場合は、シェル監査、中央ロギング、またはコマンド単位ポリシーを提供するsudoのような方式を併せて設計する必要があります。

よく発生する問題と解決方法

症状 考えられる原因 確認方法
Authentication failure 対象パスワードの誤り、アカウントロックまたはPAM制限 対象アカウントと認証ポリシー・ログの確認
切り替え後にコマンドが見つからない 対象ユーザーのPATHが異なる command -vとprintf '%s\n' "$PATH"を確認
ホームディレクトリは変更されない ログインオプションなしでsu ユーザーを使用 su --login ユーザーを使用
ユーザー設定が混ざっているように見える 既存環境を一部保持した通常のsuを使用 env、HOME、USERを確認
指定したシェルが実行されない 制限シェルまたは呼び出し権限の制限 getent passwdと/etc/shellsを確認

よくある質問

suには誰のパスワードを入力しますか?

一般的には切り替えたい対象ユーザーのパスワードを入力します。ただし、rootが実行する場合やPAMポリシーが異なる認証方式を使用する場合には動作が異なることがあります。パスワード入力中に文字を表示しない環境もあります。表示方式は実装や認証設定によるため、表示の有無だけで入力に失敗したと判断しません。

suとsu -は何が違うのですか?

suは現在のディレクトリと一部の環境を保持したままrootシェルを実行しようとします。su -はrootのホームに移動し、ログイン環境を設定します。util-linuxでは環境の混在を減らすためにログイン形式を推奨しています。

suで切り替えた後、現在のユーザーをどう確認しますか?

idは実際・有効ユーザーおよびグループを一緒に確認するのに便利です。単純なユーザー名だけが必要な場合はwhoamiを使用できますが、補助グループまで確認するならidがより多くの情報を提供します。

スクリプトにsuのパスワードを入れてもいいですか?

できません。パスワードはファイル、プロセス情報、またはログに露出する可能性があります。rootの自動化であれば制限されたrunuser、一般ユーザーの権限昇格であれば最小権限のsudoersルールや作業専用サービスのようにパスワードを内蔵しない方式を設計してください。

まとめ

一般的な対話型アカウントの切り替えはsu --login ユーザー、単一コマンドはsu -c 'コマンド' ユーザーで実行できます。単純なsu ユーザーは環境が混ざる可能性があるため、切り替え後にid、HOME、pwdを確認することを推奨します。

rootコマンドを1つ実行する目的であれば、コマンド別の権限制御と監査を提供するsudoの方が適している場合があります。root自動化で他のユーザーとして実行する場合はrunuserを検討してください。関連する基本ツールはLinuxでよく使うコマンド一覧で一緒に確認できます。