ユーザーIDに関連付けられたユーザー名を取得するPOSIX互換方式

ユーザーIDに関連付けられたユーザー名を取得するPOSIX互換方式

私はしばしばユーザー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

残念ながら、getentPOSIXはこのユーティリティを指定しないようです。

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
}

idPOSIXはUIDパラメータをサポートしていないため、eliffor句はそのパラメータがPATHにあるかどうかをidテストするだけでなく、正しく機能できるかどうかをテストします。idこれは2回実行できることを意味しますid。幸いなことに、パフォーマンスに顕著な影響はありません。idパフォーマンスへの影響を同じように無視しながら、2つを同時に実行することもできます。awk

しかし、このアプローチでは、出力を保存する必要はありません。そのうちの1つだけが実行されるため、そのうちの1つだけが関数から返された出力を印刷します。

おすすめ記事