シェルスクリプトですべてのユーザーを繰り返す方法は?
システムクリーンアップを実行するためのシェルスクリプトを作成しています。スクリプトがrootとして実行されたら、すべてのユーザーのホームディレクトリで要求されたタスクを実行したいと思います。
私はそれを繰り返すことができると思いました/etc/passwd
。しかし、そこには実際のユーザーよりも多くの項目があります。仮想ユーザーを削除する特別な方法はありますか/etc/passwd
?
私は(移植性のために)Bourne Shell用のカスタムソリューションを好みます。擬似コードと簡単な説明も歓迎します。
ベストアンサー1
既存のユーザーアカウントをすべて列挙する標準コマンドはありません。ほとんどのUnix亜種では/etc/passwd
常に同じ既存の形式(コロンで区切られた列)のローカルアカウントのリストが含まれています。 Glibc がある Linux (つまり、組み込まれていない Linux) では、次のものを使用できます。getent
コマンド:getent passwd
に似ていますcat /etc/passwd
が、リモートアカウント(NIS、LDAPなど)も含めます。
次のコードスニペットはユーザーアカウントを列挙します。
getent passwd | while IFS=: read -r name password uid gid gecos home shell; do
echo "$name's home directory is $home"
done
ユーザーデータベースには、そのユーザーが血肉であるかどうかを示す情報がないため、完全に信頼できる方法で血育ユーザーをフィルタリングすることは不可能です。 (また:テストアカウントが含まれていますか?ゲストアカウントが含まれていますか?など)適用できるいくつかの経験的な方法は次のとおりです。
ホームディレクトリがシステムディレクトリとして表示されないユーザーをフィルタリングできます。
top=${home#/}; top=${top%%/*} case $top in |bin|dev|etc|lib*|no*|proc|sbin|usr|var) echo "Looks like a system user";; *) echo "Looks like a user with a real home directory";; esac
ユーザーが自分のホームディレクトリを所有しているかどうかをテストできます。これは、システムユーザーではなく実際のユーザーの場合はほとんど常に当てはまりますが、一部のシステムユーザーは自分のホームディレクトリを持っているため、あまり信頼できません。また、通常、そのディレクトリは自動的にマウントされますが、実際のユーザーのホームディレクトリは現在利用できない場合は存在しない可能性があります。 Linuxの場合:
if [ -d "$home" ] && [ "$(stat -c %u "$home")" = "$uid" ]; then echo "Likely flesh-and-blood" else echo "Probably a system user" fi
ユーザーが実際のシェルを持っているかどうかをテストできます。ただし、多くのシステムユーザーが同じ操作を実行するため、ホームディレクトリよりも信頼性がはるかに低くなります。
アカウントにパスワードがあるかどうかをテストできます。実際のユーザーが常にパスワードを持っているわけではないので、これは完全に信頼できません(たとえば、SSHキーしか持っていない可能性があります)。システムアカウントにパスワードがある場合もあります。特にルートアカウントにパスワードがあることがよくあります。これを行う方法はUnixのバリエーションによって異なり、通常はrootアクセスが必要です。シャドウパスワード(Linuxでは一般的)があるLinuxでは、
/etc/shadow
パスワードを見つける必要があります。case $(getent shadow "$name" | awk -F: '{print $2}') in ?|??) echo "No password on this account";; |\$*) echo "This account has a password";; *) echo "Weird password field";; esac
多くのシステムでは、システムアカウントと実際のユーザーのUID範囲を定義しています。これらの範囲はシステムによって異なります。デフォルトはUnixバリアントとディストリビューションによって異なり、通常はシステム管理者が設定できます。ほとんどのLinuxディストリビューションでは、スコープは次に定義されています。
login.defs
:人間ユーザーUID_MIN
の場合、UID_MAX
他の値はシステムアカウントのものです。
私はホームディレクトリへのパスが最も信頼できる単一の指標だと思いますが、それを他の経験的な方法と組み合わせることもできます。