2

这个 shell 脚本应该将用户添加到系统中。新用户的详细信息在一个文件中。Shell 拒绝此脚本并显示以下消息:

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

第二次尝试

使用答案中的一些想法,我想出了第二次尝试:

#!/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

以 the 结尾,done而不是fi所需的 that。

循环从while前面几行开始:

cat userlist.txt | while read uname password gname fullname

缺少它的do(另一个错误);如果存在,那么最后也需要done。有人忘记了压痕。(每层使用 2 个字符优于 0 或 1,但如果每层使用 4 个空格,则更容易跟踪层。)请注意,shell 暂时没有抱怨缺少do语法循环是:

while cmd1
      cmd2
      cmd3 ...
do

就外壳而言,它仍在处理 list 中的命令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

还有很大的改进空间。如果用户不是 root,则应该退出 root 验证块;相反,这种情况发生在循环内部一英里处。您可以更好地检查参数的数量:$#为您提供参数的数量。如果我尝试过yourscript.sh '' arg2 arg3,您会声称没有参数,而实际上问题是$1存在但是一个空字符串。报告如何使用命令的标准约定类似于:

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

这会报告命令的名称和预期的参数。将1>&2消息发送到标准错误而不是标准输出。即便如此,这里的逻辑也有点奇怪。您检查用户是否是 root,然后才检查是否有参数。如果用户不是 root,则不检查参数。不完全明智,我提交。

我们可以讨论 UUOC(无用的 Cat)。实际上有一个奖项。我不认为这符合条件。但是,可以这样写:

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; 它被视为错误。

组检查结构类似,应该进行类似的升级。

您将密码读入$passwordread行;但是,在创建密码时,您有:

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

在第一个周期,$pass是空的(很可能);你应该在$password最后使用双引号:

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

egrep命令一样,您也可以useradd直接检查命令的状态。说是 tyro 的标志有点笼统if [ $? == 0 ],但也不是太离谱。

脚本中的最后exit应该是exit 1指示错误退出。正如已经指出的,这前面是关于“你必须是 root”的评论,即使在顶部检查了 root 权限。

警告:我没有尝试运行脚本;我很容易错过一些问题。但是,它确实通过sh -v -n了,因此不会留下任何严重的句法错误。

一旦一个 shell 脚本在语法上是正确的,那么你通常使用sh -x script(或者,如果它需要参数,那么sh -x script arg1 arg2 arg3 ...)来调试它。这是执行跟踪模式。shell 或多或少地告诉你它在做什么。信息写入标准错误。如果您愿意,您甚至可以捕获输出以供以后审查:

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

2>script-x.log符号将标准错误发送到文件script-x.log(选择您自己的有意义的名称;我经常使用xorxxx用于我不想保留的文件,但我也删除了这些文件而不必查看它们,因为我知道它们是一次性文件) .

于 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 回答