2

このシェル スクリプトは、ユーザーをシステムに追加することになっています。新しいユーザーの詳細はファイルにあります。シェルは、次のメッセージでこのスクリプトを拒否しています:

syntax error near unexpected token 'done'.

どうしたの?

#!/bin/bash
#Purpose: Automatically add new users in a linux system based upon the data found within a text file
#         Assign encryped passwords to each user
#         Add users to groups or create new groups for these users
#         Report errors and successful operations where necessary in log files
#         post help options (echo)

#Root validation
if [[ $(id -u) -eq 0 ]]; then
  #Argument validation
  if [[ -z "$1" ]]; then
    echo "No arguments found!"
    echo "Please include a user detail text file as first argument"
    echo "Please include a report text file as second argument"
    echo "Please include an error report text file as the third argument"
    echo "Use the -h argument (i.e. ./script -h) for help"
  exit 1
fi

#Help validation and Help file
if [[ "$1" = "-h" ]]; then
  echo "This is the help information file"
  echo "This script is designed to add users to a linux system by reading information from a user detail file (such as userlist.txt)"
  echo "The format of this user detail text file is "username password groupname fullname" seperated using TAB spacing"
  echo "This script will read the first argument as the user detail file, the second and third arguments will be read as a success report file and error report file respectively"
  exit
fi

#Reads first argument as user detail file for data
cat userlist.txt | while read uname password gname fullname
#Reads /etc/passwd for Username
egrep -w "^$uname" /etc/passwd
#If Username is found then error reports
if [ $? == 0 ]; then
  echo "User Already Exists : Error adding user with username $uname;$gname;$fullname" >> Successes1.log
  exit 1
else
  #Reads /etc/group for Groupname
  egrep -w "^$gname" /etc/group
  #If Groupname is found then nothing
  if [ $? == 0 ]; then
    echo ""
  else
    #If Groupname not found then creates new group and reports
    groupadd "$gname"
    echo "Group Not Found: New Group $gname was created" >> Successes1.log
  fi
  #Retrieves Date
  createddate=$(date)
  #Perl password script takes input from Userlist
  pass=$(perl -e 'print crypt($ARGV[0], "Password")' "$password")
  #Adds Users with variables from userlist
  useradd "$uname" -g "$gname"  -c "$fullname" -p "$pass"
  #Reports information to successlist and errorlist report files
  if [ $? == 0 ]; then
    groupid=$(id -g $uname)
    userid=$(id -u $uname)
    echo "User Successfully Added: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Successes1.log
  else
    groupid=$(id -g $uname)
    userid=$(id -u $uname)
    echo "Useradd Error Occurred: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Errors1.log
    echo "Error: Must be root user to execute script"
    exit
  fi
done

2 回目の試行

回答からのいくつかのアイデアを使用して、2 回目の試みを思いつきました。

#!/bin/bash
#Purpose: Automatically add new users in a linux system based upon the data found within a text file
#         Assign encryped passwords to each user
#         Add users to groups or create new groups for these users
#         Report errors and successful operations where necessary in log files
#         post help options (echo)

#Root validation
if [[ $(id -u) -eq 0 ]]; then
  #Argument validation
  if [[ -z "$1" ]]; then
    echo "Usage: $0 usernames report errors" 1>&2
    echo "Please include a user detail text file as first argument"
    echo "Please include a report text file as second argument"
    echo "Please include an error report text file as the third argument"
    echo "Use the -h argument (i.e. ./script -h) for help"
    exit 1
  fi
fi

#Help validation and Help file
if [[ "$1" = "-h" ]]; then
  echo "This is the help information file"
  echo "This script is designed to add users to a linux system by reading information from a user detail file (such as userlist.txt)"
  echo "The format of this user detail text file is "username password groupname fullname" seperated using TAB spacing"
  echo "This script will read the first argument as the user detail file, the second and third arguments will be read as a success report file and error report file respectively"
  exit
fi

#Reads first argument as user detail file for data
cat jan.txt | while read uname password gname fullname; do
#Reads /etc/passwd for Username
 egrep -w "^$uname:" /etc/passwd >/dev/null 2>&1
#If Username is found then error reports
if [ $? == 0 ] 
then
  echo "User Already Exists : Error adding user with username $uname;$gname;$fullname" >> Errors1.log

else
  #Reads /etc/group for Groupname
  egrep -w "^$gname" /etc/group
  #If Groupname is found then nothing
if [ $? == 0 ]; then
    echo ""
else
  #If Groupname not found then creates new group and reports
  groupadd "$gname"
    echo "Group Not Found: New Group $gname was created" >> Successes1.log
done < $1
#Retrieves Date
createddate=$(date)
#Perl password script takes input from Userlist
pass=$(perl -e 'print crypt($ARGV[0], "Password")' "$password")
#Adds Users with variables from userlist
useradd "$uname" -g "$gname"  -c "$fullname" -p "$pass"
#Reports information to successlist and errorlist report files
if [ $? == 0 ]
then
  groupid=$(id -g $uname)
  userid=$(id -u $uname)
  echo "User Successfully Added: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Successes1.log
else
  groupid=$(id -g $uname)
  userid=$(id -u $uname)
  echo "Useradd Error Occurred: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Errors1.log
  echo "Error: Must be root user to execute script"
  exit 1
fi
fi
done

これも正しく動作していないようです。今何が問題なのですか?引数と実行が表示されているようですが、ユーザーもグループも追加されていないため、ログは作成されていません

4

3 に答える 3

6

if開始時間:

if [ $? == 0 ]; then
  echo "User Already Exists : Error adding user with username ...
  exit 1
else

done必要な の代わりに で終了しfiます。

数行前に開始するwhileループ:

cat userlist.txt | while read uname password gname fullname

そのdo(別のバグ)がありません。それが存在する場合done、最後に も必要になります。誰かがインデントを見失いました。(レベルごとに 2 文字を使用する方が 0 または 1 よりも優れていますが、レベルごとに 4 つのスペースを使用すると、レベルを追跡しやすくなります。do)ループは次のとおりです。

while cmd1
      cmd2
      cmd3 ...
do

シェルに関する限り、まだリスト内のコマンドを処理していますcmd1, cmd2, cmd3, ...


これは、スクリプトの適度にインデントされたバージョンです。fiスクリプトの先頭にも抜けがありました。

#!/bin/bash
#Purpose: Automatically add new users in a linux system based upon the data found within a text file
#         Assign encryped passwords to each user
#         Add users to groups or create new groups for these users
#         Report errors and successful operations where necessary in log files
#         post help options (echo)

#Root validation
if [[ $(id -u) -eq 0 ]]
then
    #Argument validation
    if [[ -z "$1" ]]
    then
        echo "No arguments found!"
        echo "Please include a user detail text file as first argument"
        echo "Please include a report text file as second argument"
        echo "Please include an error report text file as the third argument"
        echo "Use the -h argument (i.e. ./script -h) for help"
        exit 1
    fi
fi

#Help validation and Help file
if [[ "$1" = "-h" ]]
then
    echo "This is the help information file"
    echo "This script is designed to add users to a linux system by reading information from a user detail file (such as userlist.txt)"
    echo "The format of this user detail text file is "username password groupname fullname" seperated using TAB spacing"
    echo "This script will read the first argument as the user detail file, the second and third arguments will be read as a success report file and error report file respectively"
    exit
fi

#Reads first argument as user detail file for data
cat userlist.txt | while read uname password gname fullname
do
    #Reads /etc/passwd for Username
    egrep -w "^$uname" /etc/passwd
    #If Username is found then error reports
    if [ $? == 0 ]
    then
        echo "User Already Exists : Error adding user with username $uname;$gname;$fullname" >> Successes1.log
        exit 1
    else
        #Reads /etc/group for Groupname
        egrep -w "^$gname" /etc/group
        #If Groupname is found then nothing
        if [ $? == 0 ]
        then
            echo ""
        else
            #If Groupname not found then creates new group and reports
            groupadd "$gname"
            echo "Group Not Found: New Group $gname was created" >> Successes1.log
        fi
        #Retrieves Date
        createddate=$(date)
        #Perl password script takes input from Userlist
        pass=$(perl -e 'print crypt($ARGV[0], "Password")' $pass)
        #Adds Users with variables from userlist
        useradd "$uname" -g "$gname"  -c "$fullname" -p "$pass"
        #Reports information to successlist and errorlist report files
        if [ $? == 0 ]
        then
            groupid=$(id -g $uname)
            userid=$(id -u $uname)
            echo "User Successfully Added: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Successes1.log
        else
            groupid=$(id -g $uname)
            userid=$(id -u $uname)
            echo "Useradd Error Occurred: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Errors1.log
            echo "Error: Must be root user to execute script"
            exit
        fi
    fi
done

改善の余地はまだたくさんあります。ユーザーがルートでない場合、ルート検証ブロックは終了する必要があります。代わりに、ループ内のさらに 1 マイル下で発生します。引数の数をより適切に確認でき$#ます。引数の数がわかります。私が試した場合、実際には問題は存在するが空の文字列であるyourscript.sh '' arg2 arg3場合、引数がないと主張するでしょう。$1コマンドの使用方法を報告するための標準的な規則は、次のようなものです。

echo "Usage: $0 usernames report errors" 1>&2

これは、コマンドの名前と、予想される引数を報告します。は1>&2、メッセージを標準出力ではなく標準エラーに送信します。ここでのロジックは、それでも少し奇妙です。ユーザーが root であることを確認してから、引数があることを確認します。ユーザーが root でない場合は、引数をチェックしません。完全に賢明ではありません、私は提出します。

UUOC (猫の無用な使用) について議論することができます。実際には賞があります。これは適任ではないと思います。ただし、次のように書くことは可能です。

while read uname password gname fullname
do
    ...
done < $1

うーん...スクリプトは、ユーザーを指定するファイル名の引数を取ることになっていますが、ファイル名の引数ではcatなく、固定のファイル名を取ります!

同様に、引数 2 と 3 は慎重に無視されます。ログ ファイルはハードコードされています。

egrep -w "^$uname" /etc/passwd
#If Username is found then error reports
if [ $? == 0 ]

このフラグメントは、いくつかの方法で改善できます。

if egrep -w "^$uname:" /etc/passwd >/dev/null 2>&1
then
    #If Username is found then error report

egrepこれは、コマンドの終了ステータスを直接テストします。rooまた、 userが原因で新しいユーザーが既存のユーザーとして扱われるのを防ぎますroot/dev/nullユーザーが存在する場合は何も表示されないように、出力とエラー出力が送信されます。

ユーザー名が見つかったときに終了しない方がよい場合があります。少なくとも次のエントリの処理を試みることができます。ユーザーが存在するというレポート (処理を終了させるレポート) がSuccesses1.logではなく に記録されるのも奇妙Errors1.logです。エラーとして扱われます。

グループ チェック構造は類似しており、同様にアップグレードする必要があります。

$password次のread行でパスワードを読み取ります。ただし、パスワードの作成に関しては、次のものがあります。

pass=$(perl -e 'print crypt($ARGV[0], "Password")' $pass)

最初のサイクルで$passは、空です (おそらく)。$password最後に二重引用符を使用する必要がありました。

pass=$(perl -e 'print crypt($ARGV[0], "Password")' "$password")

コマンドと同様に、egrepコマンドのステータスもuseradd直接確認できます。暴君の印であると言うのは少しif [ $? == 0 ]大げさですが、真実からそれほど離れていません.

exitスクリプトの最後exit 1は、エラー終了を示す必要があります。すでに述べたように、これには「root である必要があります」というコメントが先行していますが、root 権限のチェックが上部にありました。

警告: スクリプトを実行しようとはしていません。いくつかの問題を簡単に見逃していた可能性があります。ただし、合格sh -v -nするため、重大な構文エラーは残っていません。

シェル スクリプトが構文的に正しい場合は、通常は を使用してデバッグしますsh -x script(または、引数を取る場合はsh -x script arg1 arg2 arg3 ...)。これが実行トレースモードです。シェルは、多かれ少なかれ不可解に、それが何をしているかを伝えます。情報は標準エラーに書き込まれます。必要に応じて、後で精査するために出力をトラップすることもできます。

sh -x script arg1 arg2 arg3 2>script-x.log

表記法は2>script-x.log標準エラーをファイルに送信しますscript-x.log(独自の意味のある名前を選択してください。私は保持したくないファイルにxorをよく使用xxxしますが、そのようなファイルは使い捨てファイルであることを知っているため、必ずしもそれらを見ることさえせずに削除します) .

于 2012-04-27T06:17:46.163 に答える
0

"done" は、前の "do" と組み合わせる必要があります。スクリプトの末尾にはありません。

于 2012-04-27T04:01:38.423 に答える
0

あなたwhileには次のものがありませんdo:

cat userlist.txt | while read uname password gname fullname
do 

また

cat userlist.txt | while read uname password gname fullname; do
于 2012-04-27T06:01:14.890 に答える