1. 概要

シェルスクリプトを作成するときに、現在のログインユーザーが誰であるかを知りたい場合があります。

通常、 $ USER 変数を読み取るか、 whoami コマンドを呼び出すことで、情報を取得できます。 ただし、シェルスクリプトが sudo で呼び出された場合、このアプローチは機能しません。

このチュートリアルでは、問題を詳しく見ていきます。 さらに、ユーザーが sudo コマンドを使用してスクリプトを呼び出した場合でも、シェルスクリプトでログインユーザーを取得する手法について説明します。

2. 問題の紹介

2.1. 問題を理解する

簡単な例で問題を理解しましょう。

$ cat ./get_user.sh
#!/bin/bash

echo "Get the current login user by reading the \$USER variable: "$USER
echo "Get the current login user by the whoami command: "$(whoami)

上記のスクリプトには、echoコマンドがいくつかあります。 $USER環境変数とコマンドwhoami。によって現在のログインユーザーを出力します。

通常のユーザーkentとしてログインし、スクリプトを呼び出す場合:

kent$ ./get_user.sh 
Get the current login user by reading the $USER variable: kent
Get the current login user by the whoami command: kent

予想どおり、両方の echo コマンドは、現在のログインユーザーとしてkentを出力します。 ただし、 sudo コマンドを使用してスクリプトを呼び出したときに、それが引き続き機能するかどうかを確認しましょう。

kent$ sudo ./get_user.sh 
[sudo] password for kent: 
Get the current login user by reading the $USER variable: root
Get the current login user by the whoami command: root

今回は、パスワードを入力すると、両方のechoコマンドがrootを出力するのがわかります。 ここで、rootはスクリプトを実行する有効なユーザーです。 ただし、ログインユーザーではありません。 現在のログインユーザーはケント 。 シェルスクリプトで現在のログインユーザーを識別する方法を探しています。

2.2. whoコマンドが解決策ではない理由

ログインユーザーについて話すとき、便利なwhoコマンドを思い浮かべるかもしれません。

who コマンドを実行して、何が出力されるかを見てみましょう。

kent$ who
kent     tty7         2021-06-30 22:58 (:0)

who コマンドは、現在ログインしているユーザーを一覧表示できます。 したがって、ユーザーkentがリストされます。 それが私たちが探している正確な答えだったようです。

このスクリプトでは、 who コマンドの出力を解析して、現在のログインユーザーを取得できます。 このアイデアは、この例で機能する可能性があります。 ただし、スクリプトが不安定になります。

whoの出力を確認してみましょう。 出力ラインは1つだけです。 これは、現在、ユーザーkentのみがシステムにログインしているためです。 ただし、Linuxはマルチユーザーシステムです。 それでは、別のユーザー guest によってシステムにログインし、whoコマンドをもう一度起動してみましょう。

kent$ who
kent     tty7         2021-06-30 22:58 (:0)
guest    tty4         2021-07-04 20:26

ご覧のとおり、すべてのログインユーザーはwhoコマンドによって一覧表示されます。 つまり、スクリプトが sudo コマンドによって実行されると、whoコマンドに依存してスクリプトを実行したユーザーを区別することはできません。

これは、現在のログインユーザーを取得する場合の一般的な落とし穴でもあります。 次に、問題の安定した解決策を見つけましょう。

3. lognameコマンドの使用

lognamecoreutilsパッケージのメンバーです。 したがって、すべてのLinuxディストリビューションで利用できます。

logname コマンドは、ユーザーのログイン名を出力します。

それが私たちの問題を解決できるかどうか見てみましょう。 まず、新しいシェルスクリプトを書いてみましょう。

$ cat by_logname.sh
#!/bin/bash

echo "The login user is "$(logname)

次に、 sudo:を使用した場合と使用しない場合のシェルスクリプトを実行してみましょう。

kent$ ./by_logname.sh
The login user is kent

kent$ sudo ./by_logname.sh
[sudo] password for kent: 
The login user is kent

上記の出力が示すように、スクリプトは両方の場合でkentを出力します。 したがって、この問題はlognameコマンドを使用して解決されました。

4. $SUDO_USER変数の使用

sudo コマンドを使用すると、sudoを呼び出したユーザーの元のログイン名が変数に格納されます $SUDO_USER

それをテストするための小さなスクリプトを作成しましょう:

kent$ cat by_sudo_user.sh
#!/bin/bash

echo "The login user is $SUDO_USER"

ここで、sudoコマンドを使用してスクリプトを実行します。

$ sudo ./by_sudo_user.sh
[sudo] password for kent: 
The login user is kent

すごい! 元のログインユーザーkent。を報告します

ただし、 $ SUDO_USER 変数は、スクリプトがsudoで呼び出された場合にのみ設定されます。 通常のユーザーがスクリプトを直接呼び出す場合、 $SUDO_USER変数は空です。

kent$ ./by_sudo_user.sh 
The login user is

どちらの場合もスクリプトを機能させるために、スクリプトでBashのパラメーター置換 $ {パラメーター:-デフォルト}を使用できます。

$ {parameter:-default} は、パラメーターが設定されている場合、その値を取得することを意味します。 それ以外の場合は、default値を使用します。 

ここで、 default 部分は、固定値、シェル変数、またはコマンド置換などにすることができます。 後の例でそれらの動作を確認します。

スクリプトに戻りましょう。 まず、 $SUDO_USER変数を確認します。

  • 設定されている場合は、ユーザーが sudo を使用してスクリプトを呼び出し、 $SUDO_USERの値がログインユーザーであることを意味します。
  • それ以外の場合、 $ SUDO_USER 変数が設定されていない場合は、 $USER変数の値またはwhoamiコマンドの出力のいずれかを取得できます。

次に、このチェックをカバーするようにスクリプトを変更しましょう。

kent$ cat ./by_sudo_user.sh
#!/bin/bash

echo "The login user is ${SUDO_USER:-$USER}"
echo "The login user is ${SUDO_USER:-$(whoami)}"

上記の変更されたスクリプトでは、パラメーター置換の使用に対処するための2つの選択肢を示しました。

最後に、期待どおりに機能するかどうかをテストしましょう。

kent$ ./by_sudo_user.sh 
The login user is kent
The login user is kent

kent$ sudo ./by_sudo_user.sh
[sudo] password for kent: 
The login user is kent
The login user is kent

上記の出力は、スクリプトが両方の場合に機能することを示しています。 このようにして、問題は解決されました。

5. 結論

シェルスクリプトを作成する場合、 $ USER 変数を読み取るか、 whoami コマンドを呼び出すだけで、現在のログインユーザーを取得できます。 ただし、スクリプトが sudo コマンドで呼び出された場合、このアプローチは失敗します。

この記事では、最初に、 who コマンドを使用して、この問題を解決するための一般的な落とし穴について説明しました。 次に、シェルスクリプトで現在のログインユーザーを取得する2つの異なる方法、lognameコマンドと$SUDO_USER変数について説明しました。