過去15日間にログインしていないユーザーを識別するスクリプトを作成します。

過去15日間にログインしていないユーザーを識別するスクリプトを作成します。

質問があります:

運動は次のとおりです

過去 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このリストにはデフォルトグループ()があります。ユーザーは含まれませんfoofoo( )を補足群としたもの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解釈されます。foofoo正規表現に特別な意味を持つ文字(たとえば*[など)を含む]場合にのみ重要です。)


質問に記載されているBashスクリプトを作成するには、上記の一部が必要です。上記の一部を使用してこれにアクセスするには、2つ以上の異なる方法があります。また、ある種の「各入力を変数として読み込む」ループ、つまり

some command | while read line ; do
    # Here, "$line" iterates through the lines
    # output by some command
done

関連情報