期望不会将输入传递给bash脚本中的passwd
我试图使用expect将$ PASSWORD变量内容传递给passwd。这似乎工作,添加用户,但一旦你尝试通过ssh登录与其中一个用户,它不起作用。如果我手动设置密码,那就好了。期望不会将输入传递给bash脚本中的passwd
有没有人遇到过这个问题?
USERS=(user1 user2 user3)
generatePassword()
{
pwgen 16 -N 1
}
# Check if user is root
if [ $(whoami) != 'root' ]; then
echo "Must be root to run $0"
exit 1;
fi
# Check if pwgen is installed:
if [[ $(dpkg -s pwgen > /dev/null 2>&1; echo ${PIPESTATUS}) != '0' ]]; then
echo -e "pwgen is not installed, this script will not work without it\n\n'apt-get install pwgen'\n"
exit 1;
else
echo -e "Starting Script...\n\n"
fi
# Iterate through users and add them with a password
for i in ${USERS[@]}; do
PASSWORD=$(generatePassword)
echo "$i $PASSWORD" >> passwords
useradd -m "${i}"
echo -e "Adding $i with a password of '$PASSWORD'\n"
expect -c "
spawn passwd ${i}
expect \"Enter new UNIX password:\"
send -- \"$PASSWORD\r\"
send -- \"\r\"
expect \"Retype new UNIX password:\"
send -- \"$PASSWORD\r\"
send -- \"\r\"
"
echo -e "\nADDED $i with a password of '$PASSWORD'\n"
done
您续需要期望在所有:使用chpasswd
代替passwd
#!/bin/bash
users=(user1 user2 user3)
# Check if user is root
if [[ "$(id -un)" != 'root' ]]; then
echo "Must be root to run $0"
exit 1
fi
# Check if pwgen is installed:
if ! dpkg -s pwgen > /dev/null 2>&1; then
printf "pwgen is not installed, this script will not work without it\n\n'apt-get install pwgen'\n"
exit 1
else
printf "Starting Script...\n\n"
fi
# Iterate through users and create a password
passwords=()
for user in "${users[@]}"; do
useradd -m "$user"
password="$user:$(pwgen 16 -N 1)"
passwords+=("$password")
echo "Adding user '$user' with '$password'"
done
printf "%s\n" "${passwords[@]}" | chpasswd
我已经添加了这些需要几个引号。
我简化了dpkg检查。
或者,也许更简单,newusers
自动执行“useradd”和“passwd”函数。
for user in "${users[@]}"; do
password="$user:$(pwgen 16 -N 1)"
password=${password//:/-} # replace all colon with hyphen
printf "%s:%s::::/home/%s:/bin/bash\n" "$user" "${password//:/-}" "$user"
done | newusers
我不认为newusers从/ etc/skel中填充home目录。
第一:最紧迫的问题是,你是不是逃避反斜杠文字,当你键入\r
,所以这些都只是变成r
S于该expect
侧;看来解决问题的最小可能变化是将其更改为\\r
。
但是 - 不要这样做的:在expect
与其他语言,字符串可以作为文字传递,没有代入代码。
expect -f <(printf '%s\n' '
set username [lindex $argv 0];
set password [lindex $argv 1];
spawn passwd $username
expect "Enter new UNIX password:"
send -- "$password\r"
send -- "\r"
expect "Retype new UNIX password:"
send -- "$password\r"
send -- "\r"
') -- "$i" "$PASSWORD"
你也可以有问题的文字文本保存到一个文件,并运行expect -f passwd.expect -- "$i" "$PASSWORD"
,这将很好的工作(并避免对<()
语法,这是庆典采用了KSH扩展的依赖)。
我可能会以Un _expect_ ed方式使用Expect ... 我是否正确假设我需要[lindex $ argv 0]部分?我认为这是需要的,如果我在我的脚本的开头使用参数? – Detnon
所以,re:'[lindex $ argv 0]'部分,这样做是将变量从命令行拖到awk中。 (在'--'后面的末尾,我们将shell变量放在awk命令行后面;'set username'和'set password'是我们获取这些命令行参数并创建awk变量的地方)。 –
这样做而不是直接将值代入awk脚本的目的是通过令人惊讶或恶意的用户名或密码来避免注入攻击。请参阅https://xkcd.com/327/以快速介绍可防止此类攻击的SQL等效项;保持数据不被注入代码的最好方法是*从代码*中带外传输数据,这是在这里执行的。 –
Ewww。你正在对你打算作为代码解析的内容进行字符串替换?这是一个重要的代码异味 - 如果用户被允许设置自己的密码,这可能被用作任意指令注入漏洞。 –
顺便说一句,请参阅http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html了解有关环境变量名称的POSIX约定(以及因此共享一个命名空间的shell变量的名称) - 全部大写的名称是由具有含义的变量用于shell或操作系统,至少包含一个小写字符的名称被保留供应用程序使用;因此,考虑使用'password'而不是'PASSWORD'来避免错误地覆盖一个有意义的变量。 –
@CharlesDuffy - 我知道,这是一小时摸索无知的结果!我试图变得更好 – Detnon