質問があります:
運動は次のとおりです
過去 15 日間ログインしておらず、「alumnos」グループに属するユーザーを検索するスクリプトを作成します。リストは/var/log/alumnos_sin_loginに追加されます。
私のアプローチ:
#2)
#!/bin/bash
#Scripts which detects users whose group is "alumnos" who have been not logged in,
#in the last 15 days. The users' list is added to /var/log/alumnos_sin_login
#RESULTADO holds those users who haven't entered in the last 15 days
#LISTA holds alumnos' users' list
#USUAEIO actual user being parsed
#RAIZ != "" if user has logged -15 days
#Read and check if group is not created
exec 0 </etc/gshadow
if [ $(grep "alumnos:") -e ]
then
echo "Grupo alumnos no existe"
exit 1
fi
RESULTADO="Los alumnos que llevan más de 15 días sin loguearse son: "
LISTA=$(grep "alumnos:" | cut -d ':' -f 4)
IFS=,
for USUARIO in $LISTA
do
RAIZ=$(find /home/$USUARIO -atime +15 | grep "/home/$USUARIO")
if [ $RAIZ != "" ]
then
RESULTADO="$RESULTADO $USUARIO"
fi
done
echo $RESULTADO >> /var/log/alumnos_sin_login
exit 0
Q:この文をどのように改善できますか?
if [ $(grep "alumnos:") -e ]
グループが作成されたことを確認してください。存在しない場合は正常に機能しますが、存在する場合は次のように報告します。
bash: [: ==: unary operator was expected
なぜ?
次に、ユーザーが過去15日間にログインしていないことを知るためのより良い方法はありますか?コードは、そのディレクトリが/home/name_of_userであり、標準ではないと仮定しているためです。私は、最後のユーザーのログイン時間を取得するコマンドがあるのか、それとも少なくとも自分のディレクトリを正しく知る方法があるのかわからないからです。
ご協力ありがとうございます。
答え1
過去15日間にログインしていないユーザーのリストを取得する最も簡単な方法は、/home
次のlastlog
コマンドを使用することです。
lastlog -b 15
出力行を表示します。
alumno1 pts/14 172.17.1.114 2016年10月22日 土曜日 22:18:57 +0100
名前(最初のフィールド)のみを希望する場合:
lastlog -b 15 | sed "1d" | awk ' { print $1 } '
(ヘッダーをsed "1d"
削除するために使用される場合lastlog
)
~から男の最後の記録:
オプション lastlog コマンドで使用できるオプションは次のとおりです。
-b, --before DAYS Print only lastlog records older than DAYS.
ユーザーがログインしたことがない場合は、ポートと時刻の代わりに「ログインしていません」というメッセージが表示されます。
グループを検証する実際のスクリプトは次のとおりです。
#!/bin/bash
getent group alumnos > /dev/null
if [ $? -ne 0 ]
then
echo "group alumnos does not exist"
exit 1
fi
for i in ` lastlog -b 15 | sed "1d" | awk ' { print $1 } '`
do
if [ `id -ng $i` == "alumnos" ]
then
echo $i
fi
done
exit 0
ここで、
変数は、現在の繰り返し「$i」が指すユーザーグループの名前が与えられたら、指定されたi
すべてのユーザーの名前を繰り返し、グループが存在することを確認します。lastlog
id -ng user
getent group alumnos
if
言及したエラーは、何も見つからないとオペランドがgrep
欠落して空になります。トリックの1つは、次のように文字列比較を「x」で埋めることです。
if [ "x"$i == "xstring" ]
then
...
グループ同窓会があることを確認する別のオプション:
if [ $(grep "^alumnos:" /etc/group) -e ]
then
echo "No group alumnos"
exit 1
fi
複数のグループのユーザーを確認する別のオプション:
groups user | grep alumnos
答え2
補足グループに属するユーザーをリストするには、foo
次のようにします。
getent group foo | cut -d ':' -f 4- | tr -s '\n,' '\n\n'
これgetent
このコマンドは「名前サービススイッチ」を使用します。これは、ユーザー情報とパスワードがリモートサーバーに保存されているシステムでもgetent
ユーザー情報を引き続き取得できることを意味します。
getent passwd
解析する代わりに/etc/passwd
getent group
解析する代わりに/etc/group
上から3番目の引数を指定すると、その項目のみが表示されます。 (shadow
およびgshadow
、しかしgetent
特別な権限を持つユーザーにのみ情報を提供します。)
出力はgetent group foo
次のようになります。
foo:x:1001:user1,user2,user3
ここで、最初のフィールドはグループ名、2番目のフィールドはグループパスワード(*
パスワードがない場合、またはx
ファイルにのみ存在する場合gshadow
)、3番目のフィールドはグループID番号、4番目のフィールドはカンマ区切りのリストです。ユーザーはこのグループをセカンダリグループとして設定できます。
このcut -d ':' -f 4-
コマンドは、各行からコロンで区切られた最初の3つのフィールドを削除します。 (つまり、各入力行から4番目以降のコロンで区切られたフィールドのみが出力されます。)これにより、グループ名、パスワード参照、およびグループID番号が削除されます。
すべてのコンマを改行に変換しtr -s '\n,' '\n\n'
、すべての連続した改行(およびコンマ)を単一の改行に結合します。
foo
したがって、出力は補助グループとしてのユーザー名であり、1行に1つのユーザー名です。
id -gn
このリストにはデフォルトグループ()があります。ユーザーは含まれませんfoo
。foo
( )を補足群としたものid -Gn
。
foo
基本グループのユーザーを一覧表示するには、次のようにします。
getent passwd | awk -F ':' '$4=='$(id -g foo)' { print $1 }'
今回は、passwdデータベース全体をダンプしてくださいawk
。
この$(id -g foo)
部分は実際に一重引用符の外側にあるため、グループのグループID番号に展開されますfoo
。 awkルールは、各行のコロンで区切られた4番目のフィールドをfoo
(グループ内の)グループID番号と比較し、一致すると最初のフィールド(ユーザー名)を印刷します。
これlastlog
このコマンドを使用すると、ユーザーのログイン履歴を取得できます。この-t
オプションを使用すると、レコードが考慮される日数を指定できます。
コマンド出力(特に日付形式)がローカライズされlastlog
ました。これは、ユーザーのロケールが出力に日付が表示される方法に影響を与えることを意味しますlastlog
。出力が常に英語で英語の日付形式を使用するようにするには、次のようにします。
LANG=C LC_ALL=C lastlog
これはLANG=C LC_ALL=C
、ロケール設定を指定するために最も一般的に使用される2つの環境変数です。シェルを使用すると、個々のコマンドの環境をコマンド自体の前に配置して一時的にオーバーライドできます。
たとえば、過去10日間にログインしていないユーザーのみを一覧表示するには、次のようにします。
LANG=C LC_ALL=C lastlog -t 10 | awk '/Never logged in/ { print $1 }'
ただし、これがfoo
そのグループのメンバーに選択を制限するわけではありません。
ユーザーがどの補助グループに属しているかをいつでも確認できます。
id -gn username
Bashでは、次のものを使用できます。
groups=" $(id -gn "$user") "
if [ "${groups// foo / }" != "$groups" ]; then
# user $user is a member of group foo
else
# user $user is not a member of group foo
fi
ユーザーが$user
グループのメンバーであることを確認してくださいfoo
。 (つまり、プライマリグループではなくセカンダリグループのみを確認してください。各ユーザーには、を使用して取得できるプライマリグループがあります。id -Gn "$user"
)
これは、先行スペースと後続スペースを使用してスペースで区切られた$groups
ユーザー補助グループのリストに最初に設定されるために機能します。$user
引用を参照してください!Bash式は${groups// foo / }
値に拡張さ$groups
れますが、みんな(先行および末尾のスペースを参照)のインスタンスがfoo
削除されました(スペースに置き換えます)。
この句は、if
削除された値$groups
と削除された値をfoo
比較します$groups
。 2つが異なる場合は$group
含める必要がありますfoo
。これが気に入らない場合は、同等のものを使用できます
if id -Gn "$user" | tr -s ' \n' '\n\n' | grep -qxF foo ; then
# user "$user" is a member of group foo
fi
ここでは、tr
すべての連続したスペースと改行文字が改行文字にグループ化され、グループ名が独自の行に分割されます。grep -qxF foo
「静かな」grep()を実行します。つまり、何も出力せずに成功または失敗のみを返します-q
(Bashなどのパイプコマンドでは、成功/失敗はパイプの最後のコマンドによって決まります)。-x
私たちはすべてのグループを受け入れるわけではありません持つ foo
その中で、団体のみ正確に一致 foo
);最後に、-F
オプションは正規表現ではなく固定文字列としてgrep
解釈されます。foo
(foo
正規表現に特別な意味を持つ文字(たとえば*
、[
など)を含む]
場合にのみ重要です。)
質問に記載されているBashスクリプトを作成するには、上記の一部が必要です。上記の一部を使用してこれにアクセスするには、2つ以上の異なる方法があります。また、ある種の「各入力を変数として読み込む」ループ、つまり
some command | while read line ; do
# Here, "$line" iterates through the lines
# output by some command
done