Using the passwd command from within a shell script
I’m writing a shell script to automatically add a new user and update their password. I don’t know how to get passwd to read from the shell script instead of interactively prompting me for the new password. My code is below.
15 Answers 15
--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
[Update] a few issues were brought up in the comments:
Your passwd command may not have a —stdin option: use the chpasswd utility instead, as suggested by ashawley.
If you use a shell other than bash, «echo» might not be a builtin command, and the shell will call /bin/echo . This is insecure because the password will show up in the process table and can be seen with tools like ps .
In this case, you should use another scripting language. Here is an example in Perl:
#!/usr/bin/perl -w open my $pipe, '|chpasswd' or die "can't open pipe: $!"; print "$username:$password"; close $pipe
You should quote your parameter expansions. Moreover; this is in no way shape or form portable or even recommended in the slightest. See my reply for some more information on the topic.
Please don’t use echo . | password! The password will then be visible to any other users who run ps. And the more places you pass the password through (different programs, files, pipes, etc), the higher the chances are that it will leak out somewhere.
@lhunath: you are right about the quoting, I’ll fix that. @Brian: «echo» is a bash builtin, it will not show up in ‘ps’ output (at least in bash, not sure about sh)
@glennjackman please note that here strings implicitly create temporary files that may be readable by outside sources.
The only solution works on Ubuntu 12.04:
echo -e "new_password\nnew_password" | (passwd user)
But the second option only works when I change from:
echo "password:name" | chpasswd
echo "user:password" | chpasswd
See explanations in original post: Changing password via a script
What if the password contains a «\n» in the first case? There is a way to handle this? Such as my@secret\npasword123
Similar to the first but automatically repeats the password. Also, use sudo otherwise it will ask for current password first and mess this up. echo password | sed ‘s/.*/\0\n\0/’ | sudo passwd -q $USER 2> /dev/null
Nowadays, you can use this command:
For some reason I received the following error when trying your command: «Authentication token manipulation error». Adding sudo before chpasswd fixed this for me.
@LaurentVanWinckel — chpasswd only works with sudo / root rights. Therefore, to execute it as an user other than root , that user has to be in the sudo group: echo ‘user:pass’ | sudo chpasswd . When executing this one-liner on a prompt, make sure to prepend it with an additional space. Otherwise the command including the sensitive password will likely be written to the user’s prompt history file, e.g. ~/.bash_history .
Nothing you can do in bash can possibly work. passwd(1) does not read from standard input. This is intentional. It is for your protection. Passwords were never intended to be put into programs, or generated by programs. They were intended to be entered only by the fingers of an actual human being, with a functional brain, and never, ever written down anywhere.
Nonetheless, we get hordes of users asking how they can circumvent 35 years of Unix security.
It goes on to explain how you can set your shadow(5) password properly, and shows you the GNU-I-only-care-about-security-if-it-doesn’t-make-me-think-too-much-way of abusing passwd(1) .
Lastly, if you ARE going to use the silly GNU passwd(1) extension —stdin , do not pass the password putting it on the command line.
echo $mypassword | passwd --stdin # Eternal Sin. echo "$mypassword" | passwd --stdin # Eternal Sin, but at least you remembered to quote your PE. passwd --stdin
The last is the best you can do with GNU passwd . Though I still wouldn't recommend it.
Putting the password on the command line means anyone with even the remotest hint of access to the box can be monitoring ps or such and steal the password. Even if you think your box is safe; it's something you should really get in the habit of avoiding at all cost (yes, even the cost of doing a bit more trouble getting the job done).
How to change *your* Linux password via a Bash script
It's easy enough to change another user's password via a Bash script - just do echo newpw | sudo passwd username and bam, you're done. But if you run echo newpw | passwd username it doesn't work because it prompts you for your current password before letting you enter in your new password. How to change your password via Bash?
Only root can use passwd username for a different user. When you run passwd (without username ) as root it does not ask for the old password (on my Ubuntu 19.10 system).
Well, give it the current password then, < sleep .1; echo OLDPASSWORD; for i in 1 2; do sleep .1; echo Trump2020! ; done; >| passwd . Use . | script -c passwd /dev/null if passwd wants to read from a tty. But you really shouldn't be doing that. Better say what you're trying to achieve.
3 Answers 3
For all us newbies, can you help me understand the need for
@topher217 This is a here-string to provide input to a file descriptor (similar to a here-document ) by default to STDIN or fd0. See here
Thanks @JRFerguson. I also found these examples helpful. I'm not sure if I am wording this correctly, but now I understand that running chpasswd opens a kind of interactive STDIN terminal as opposed to expecting some string positional argument. You're idea of using a here-string makes the usage of chpasswd resemble the syntax of a single line positional argument. I also found reading the man page for cat and comparing the examples of using it with and without a file positional arg helpful.
If you want to change the passwd of the current user, this should do as well:
echo -e "MyOldPasswd\nMyNewPasswd\nMyNewPasswd" | passwd
That won't work with any halfway reasonable setup. Only root can change other user's passwords, via passwd user (it should prompt for the new password). To change your own password, do passwd , it should ask for the current password an then ask for the new one (and confirmation).
Allowing any random user to change other's passwords is a huge security problem.
Why "That won't work with any halfway reasonable setup" and "Allowing any random user to change other's passwords"? This answer is unrelated to the current question. The current question is about changing your password. That works. That is secure.
@ValerioBozz I'd disagree. If the premise is wrong then any expectation about an answer will also be wrong
@roaima Maybe we are on different premises. The user already said «I was doing sudo». So anwering «Only root can change» is not useful to the user. It seems the user is not interested in avoiding root. We don't need to say why root is necessary.
@ValerioBozz the OP seems confused about sudo . They demonstrate that they can use sudo to forcibly change any password without entering the old one, and then ask why (without sudo ) they have to enter their current password before being able to change it. Secondly, I think there may be an English language confusion. Someone can use "your" to mean any of "your" (of you, to whom I'm speaking) or "someone" (possibly including "me" and "you", but also anyone else). I think the last sentence is intended to mean "How can I change my password without needing to know the previous one?"
Меняем пароль пользователю из bash скрипта (или просто командой из шелла).
Сейчас на КИТе нашли отличный способ сменить пароль пользователю из шелла (а значит и из скрипта). В общем, кто сталкивался с этой проблемой — поймут меня.
UPD: в комментариях указали другой способ смены пароля от рута:
root@host:~# echo "username:password" | chpasswd
Такой способ тоже подходит, но не является универсальным. Например, во FreeBSD утилиты chpasswd нет.
EOUPD
Сменим пароль руту на megapassword (запуск от рута):
root@host:~# echo -e "megapassword\nmegapassword\n" | passwd
Сменим пароль пользователю username (запуск от рута)
root@host:~# echo -e "megapassword\nmegapassword\n" | passwd username
Для того, что бы было понятнее, покажу что в кавычках с пробелами:
«megassword \n megapassword \n», где megapassword — новый пароль, а \n — «нажатие» клавиши enter (а точнее — перенос строки)
Сменим пароль пользователю username при запуске от username:
username:~$ echo -e "oldpassword\nmegapassword\nmegapassword\n" | passwd
Здесь добавляется третья строка в выводе echo, в которой нужно указать старый пароль. Чего я в общем-то вам не советую.
Ну и чтобы не было вопросов о том, что происходит:
inky@laptop1:~$ echo -e "oldpassword\nmegapassword\nmegapassword\n"
oldpassword
megapassword
megapassword
То есть мы на STDIN passwd скармливаем STDOUT echo. А echo и «жмет enter»