Bash - 提示uid,循环用户直到输入有效输入,验证/ etc / passwd中的所有uid

时间:2017-04-27 16:42:28

标签: bash

以下是我被要求做的事情:

  • 编写脚本以提示用户输入有效的uid。在脚本中验证以下内容并不断提示用户,直到他们提供有效输入(使用循环)。告诉我你的脚本,它工作,即你做了一些测试。在您的反馈中应满足以下要求并进行测试:

    1. 数量小于65537
    2. 数量超过1000
    3. 验证来自/ etc / passwd的所有uid并确保它尚未使用。

我不确定他的意思是数字小于65537或数字超过1000,但这是我迄今为止所拥有的。

#!bin/bash
read -p "Enter a username: " uname
users=`awk -F: '{print $1}' /etc/passwd | sort`
while [[ -z "$uname ]]; do
    echo""
    echo "Error: Must supply a username!"
    echo ""
    read -p "Enter a username: " uname
    echo ""
for user in $users; do
    if [[ "$user" == "$uname" ]]; then
             echo "$uname exists"
             break
    else
             echo "doen't exist"
    fi
done
for user in $users; do
        if [[ "$user" == "$uname" ]]; then
                echo "$uname exists"
                exit
        else
                echo "doesn't exist"
                exit
        fi
done

显然我对此非常荒谬,所以任何帮助都会令人难以置信

3 个答案:

答案 0 :(得分:2)

#!/bin/bash
until (( uid < 65537 )) && (( uid > 1000 )) && ! getent -s files passwd $uid > /dev/null
do
    read -p "Enter a UID: " uid
    if(( uid > 65537 )) || (( uid < 1000 )); then
        echo "UID must be within 1001 - 65536" >&2
    elif getent -s files passwd $uid > /dev/null; then
        echo "UID $uid is already in use" >&2
    fi
done

虽然您的问题指定了/etc/passwd文件,但建议您使用getent实用程序。通过添加-s files选项,它会告诉getentfiles支持的密码读取。

答案 1 :(得分:0)

#!/usr/bin/env bash

declare -a uids_in_use=( )
while IFS=: read -r _ _ file_uid _; do
  (( f )) && uids_in_use[$file_uid]=1 ||:
done </etc/passwd

while read -r -p "Enter a UID:" entered_uid; do      
  if (( entered_uid < 1000 )); then
    echo "UIDs below 1000 are reserved for system use!" >&2
    continue
  fi
  if (( entered_uid > 65536 )); then
    echo "Maximum UID value is 65536!" >&2
    continue
  fi
  if [[ ${uids_in_use[$entered_uid]} ]]; then
    echo "UID $entered_uid is already in use!" >&2
    continue
  fi
  echo "UID $entered_uid is acceptable!"
  break
done

注意事项:

  • 阅读文件的最佳做法是使用while read循环,如BashFAQ #1中所述。在这种特殊情况下,IFS=: read -r _ _ uid _将行的第三个字段读入变量uid,通过将其结果分配给占位符变量{{1}来丢弃第一个,第二个字段和所有后续字段集。 }}。
  • 特别参见Why You Don't Read Lines With for,关于_是不良做法。 (这会扩展全局 - 从而用{}替换for user in $users的条目,忽略引用并转换为拆分IFS中的空格或其他字符等等。
  • UID是与每个用户名相关联的数字。作业要求您查找有效的,未使用的UID - 未使用的用户名。
  • *创建算术上下文。请参阅http://wiki.bash-hackers.org/syntax/arith_expr - 在此上下文中,C样式语法可用于整数数学。 (对于需要浮点数学的其他情况,请参阅BashFAQ #22)。
  • (( ))声明一个数字索引数组。请参阅http://wiki.bash-hackers.org/syntax/arraysBashFAQ #5。 bash中的数组是稀疏的 - 也就是说,你可以在它之前没有999个其他元素的情况下分配给元素1000,这是我们在这里使用的属性。 declare -a分配给数组元素,而array[$idx]=value执行查找。

答案 2 :(得分:0)

我这样做

# validate the new uid is in the usable range or error
valid_range() {
   local uid="$1"

   if [[ $uid -lt 65537 && $uid -gt 1000 ]]; then
      return 0
   else
      echo "Invalid range" >&2
      return 1
   fi
}

# make sure the uid is not in use
unused() {
   local uid="$1"

   awk -F: -v u=$uid '{if ($3 == u){print "Uid in use"; exit 1} }' /etc/passwd
}


declare -i new_uid=''
while sleep .5; do
   read -rp "Enter a new uid: " new_uid;

   if valid_range $new_uid && unused $new_uid; then
      break     # exit once we get a valid unused uid
   fi
done

我只接受整数,我有一个小的内置睡眠以保持它的皮带,我有错误信息解释发生了什么,它相当小,很容易读取。