私はしばしばユーザーIDに関連付けられたログイン情報を取得したいのですが、これが一般的なユースケースであることが証明されているため、これを行うためのシェル関数を作成することにしました。私は主にGNU / Linuxディストリビューションを使用しますが、可能な限り移植可能なスクリプトを作成しようとし、私がやっていることがPOSIXと互換性があることを確認します。
分析する/etc/passwd
私が試した最初の方法は解析/etc/passwd
(使用awk
)でした。
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
ただし、このアプローチの問題は、ログインがローカルではない可能性があることです。例えば、ユーザ認証は、NISまたはLDAPを介して行うことができる。
getent
コマンドの使用
を使用すると、ローカルではなくNISまたはLDAPデータベースも照会されるため、getent passwd
解析よりも移植性が優れています。/etc/passwd
getent passwd "$uid" | cut -d: -f1
残念ながら、getent
POSIXはこのユーティリティを指定しないようです。
id
コマンドの使用
id
ユーザーの身元に関するデータを取得するためのPOSIX標準化ユーティリティ。
BSD および GNU の実装では、ユーザー ID をオペランドとして受け入れます。
これは、ユーザーIDに関連付けられたログインを印刷するために使用できることを意味します。
id -nu "$uid"
ただし、POSIX はユーザー ID をオペランドとして提供することを指定しません。ログイン名オペランドとして。
上記のすべてを組み合わせてください。
上記の3つの方法を次のように組み合わせることを検討しました。
get_username(){
uid="$1"
# First try using getent
getent passwd "$uid" | cut -d: -f1 ||
# Next try using the UID as an operand to id.
id -nu "$uid" ||
# As a last resort, parse `/etc/passwd`.
awk -v uid="$uid" -F: '$3 == uid {print $1}' /etc/passwd
}
しかし、これは寛大でエレガントではなく、より重要なことには十分に堅牢ではありませんでした。ユーザーIDが無効または存在しない場合は、ゼロ以外の状態で終了します。各コマンド呼び出しの終了ステータスを解析して保存するための長くて薄暗いシェルスクリプトを書く前に、ここに尋ねたいと思いました。
ユーザーIDに関連付けられたログインを取得するよりエレガントで移植可能な(POSIX互換)方法はありますか?
ベストアンサー1
一般的なアプローチは、目的のプログラムが存在するかどうか、から検索できるかどうかをテストすることですPATH
。
get_username(){
uid="$1"
# First try using getent
if command -v getent > /dev/null 2>&1; then
getent passwd "$uid" | cut -d: -f1
# Next try using the UID as an operand to id.
elif command -v id > /dev/null 2>&1 && \
id -nu "$uid" > /dev/null 2>&1; then
id -nu "$uid"
# Next try perl - perl's getpwuid just calls the system's C library getpwuid
elif command -v perl >/dev/null 2>&1; then
perl -e '@u=getpwuid($ARGV[0]);
if ($u[0]) {print $u[0]} else {exit 2}' "$uid"
# As a last resort, parse `/etc/passwd`.
else
awk -v uid="$uid" -F: '
BEGIN {ec=2};
$3 == uid {print $1; ec=0; exit 0};
END {exit ec}' /etc/passwd
fi
}
id
POSIXはUIDパラメータをサポートしていないため、elif
for句はそのパラメータがPATHにあるかどうかをid
テストするだけでなく、正しく機能できるかどうかをテストします。id
これは2回実行できることを意味しますid
。幸いなことに、パフォーマンスに顕著な影響はありません。id
パフォーマンスへの影響を同じように無視しながら、2つを同時に実行することもできます。awk
しかし、このアプローチでは、出力を保存する必要はありません。そのうちの1つだけが実行されるため、そのうちの1つだけが関数から返された出力を印刷します。