在shell脚本中使用passwd命令

时间:2009-04-03 17:34:53

标签: linux bash unix shell

我正在编写一个shell脚本来自动添加新用户并更新其密码。我不知道如何让passwd从shell脚本中读取而不是以交互方式提示我输入新密码。我的代码如下。

adduser $1
passwd $1
$2
$2

14 个答案:

答案 0 :(得分:82)

来自“man 1 passwd”:

   --stdin
          This option is used to indicate that passwd should read the new
          password from standard input, which can be a pipe.

所以在你的情况下

adduser "$1"
echo "$2" | passwd "$1" --stdin

[更新]评论中提出了一些问题:

您的passwd命令可能没有--stdin选项:使用chpasswd 相反,如ashawley所示。

如果使用bash以外的shell,“echo”可能不是内置命令, shell会调用/bin/echo。这是不安全的,因为密码 将显示在流程表中,可以使用ps等工具查看。

在这种情况下,您应该使用其他脚本语言。以下是Perl中的一个示例:

#!/usr/bin/perl -w
open my $pipe, '|chpasswd' or die "can't open pipe: $!";
print {$pipe} "$username:$password";
close $pipe

答案 1 :(得分:47)

唯一的解决方案适用于Ubuntu 12.04:

echo -e "new_password\nnew_password" | (passwd user)

但第二个选项仅在我改变时才有效:

echo "password:name" | chpasswd

要:

echo "user:password" | chpasswd

请参阅原始帖子中的说明:Changing password via a script

答案 2 :(得分:25)

阅读以下明智的词语:

我引用:

  

你在bash中所做的一切都无法奏效。 passwd(1)不读取标准输入。这是故意的。这是为了你的保护。密码从未打算放入程序或由程序生成。它们只能由一个真实的人类的手指进入,具有功能性的大脑,并且永远不会在任何地方写下来。

     

尽管如此,我们仍有大批用户询问他们如何规避35年的Unix安全。

接着解释如何正确设置shadow(5)密码,并向您展示GNU- I-only-care-about-security-if-it-not-make-我认为太多了 - 滥用passwd(1)

最后,如果您打算使用愚蠢的GNU passwd(1)扩展名--stdin不要传递密码,将其放在命令行上。

echo $mypassword | passwd --stdin # Eternal Sin.
echo "$mypassword" | passwd --stdin # Eternal Sin, but at least you remembered to quote your PE.
passwd --stdin <<< "$mypassword" # A little less insecure, still pretty insecure, though.
passwd --stdin < "passwordfile" # With a password file that was created with a secure `umask(1)`, a little bit secure.

最后一个是你用GNU passwd做的最好的事情。虽然我仍然不推荐它。

将密码放在命令行上意味着任何拥有最远程访问权限的人都可以监控ps等,并窃取密码。即使你认为你的盒子是安全的;你应该真正养成不惜一切代价避免的习惯(是的,甚至是完成工作时遇到的麻烦)。

答案 3 :(得分:23)

如今:

echo "user:pass" | chpasswd

答案 4 :(得分:1)

你可以使用chpasswd

echo $1:$2 | chpasswd

答案 5 :(得分:1)

对于那些需要以root身份运行的人来说,&#39;远程通过脚本登录到sudoers文件中的用户帐户,我发现了一个邪恶可怕的黑客,这无疑是非常不安全的:

sshpass -p 'userpass' ssh -T -p port user@server << EOSSH
sudo -S su - << RROOT
userpass
echo ""
echo "*** Got Root ***"
echo ""
#[root commands go here]
useradd -m newuser
echo "newuser:newpass" | chpasswd
RROOT
EOSSH

答案 6 :(得分:1)

如果您的passwd不支持--stdin,并且您不想(或不能)使用chpasswd用于

此处文档出于某些原因。

示例:

#!/usr/bin/env bash

username="user"
password="pass"

passwd ${username} << EOD
${password}
${password}
EOD

在Arch Linux下测试。 passwdshadow-utils的元素,并且是从core/filesystem软件包安装的,由于core/base需要该软件包,因此通常默认情况下安装该软件包。

答案 7 :(得分:0)

您是否查看了-p的{​​{1}}选项(AFAIK只是adduser的另一个名称)?您可能还想查看带有明文密码的useradd -P选项,但我不知道luseradd是否是标准命令(它可能是SE Linux的一部分)或者只是一个奇怪的Fedora)。

答案 8 :(得分:0)

在我为这类事情保留的CentOS VMWare图像上进行了测试。请注意,您可能希望避免将密码作为命令行参数,因为整个计算机上的任何人都可以从'ps -ef'中读取它们。

那说,这将有效:

user="$1"
password="$2"
adduser $user
echo $password | passwd --stdin $user

答案 9 :(得分:0)

有时设置一个没人知道的密码很有用。这似乎有效:

tr -dc A-Za-z0-9 < /dev/urandom | head -c44 | passwd --stdin $user

答案 10 :(得分:0)

我偶然发现同样的问题,由于某种原因,“ - stdin”选项在我使用的passwd版本上没有提供(在Ubuntu 14.04上发布)。

如果你们中的任何一个碰巧尝试了同样的事情,你可以像我一样工作:使用这样的chpasswd命令:

echo "<user>:<password>" | chpasswd

答案 11 :(得分:0)

这是teradata节点管理员的明确答案。

转到/etc/hosts文件,在文本文件中创建IP或节点名称列表。

SMP007-1
SMP007-2
SMP007-3

将以下脚本放在文件中。

#set a password across all nodes
printf "User ID: "
read MYUSERID
printf "New Password: "
read MYPASS

while read -r i; do
    echo changing password on "$i"
    ssh root@"$i" sudo echo "$MYUSERID":"$MYPASS" | chpasswd
    echo password changed on "$i"
done< /usr/bin/setpwd.srvrs

好的,我知道我已经破坏了ssh和root的基本安全规则 但我会让安全人员处理它。

现在将其与您的/usr/bin配置文件一起放在setpwd.srvrs子目录中。

运行该命令时,它会提示您一次输入用户ID 然后一次输入密码。然后脚本遍历所有节点 在setpwd.srvrs文件中,为每个节点执行无密码ssh, 然后设置密码,无需任何用户交互或辅助 密码验证。

答案 12 :(得分:0)

对于我在 Raspbian 上它只能这样工作(添加旧密码):

#!/usr/bin/env bash

username="pi"
password="Szevasz123"
new_ps="Szevasz1234"

passwd ${username} << EOD
${password}
${new_ps}
${new_ps}
EOD

答案 13 :(得分:-1)

您可以使用the expect utility来驱动从tty读取的所有程序(而不是stdin,这是passwd所做的)。 Expect随附了各种交互式问题的示例,例如passwd entry。