<> == I want to set a user's password using the Unix passwd command, but how do I script that? It doesn't read standard input! == OK, first of all, I ''know'' there are going to be some people reading this, right now, who don't even understand the question. Here, this '''does not work''': {{{ { echo oldpass; echo newpass; echo newpass; } | passwd # This DOES NOT WORK! }}} Nothing you can do in bash can ''possibly'' work. The traditional `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. So before you continue, consider the possibility that the authors of `passwd(1)` were on to something, and you probably '''shouldn't''' be trying to script `passwd(1)` input. Nonetheless, we get hordes of users asking how they can circumvent 35 years of Unix security. And we get people contributing their favorite security-removing "solutions" to this page. If you still ''think'' this is what you want, read on. === Construct your own hashed password and write it to some file === The first approach involves constructing your own hashed password (DES, MD5, Blowfish, or whatever your OS uses) using nonstandard tools such as http://wooledge.org/~greg/crypt/ or Debian/Ubuntu's `mkpasswd` package. You would then write that hashed password, along with additional fields, in a line in your system's local password-hash file (which may be `/etc/passwd`, or `/etc/shadow`, or `/etc/master.passwd`, or `/etc/security/passwd`, or ...). This requires that you read the relevant man pages on your system, find out where the password hash goes, what formatting the file requires, and then construct code that writes it out in that format. A minor variant of this involves using a system-specific tool to write the line for you, given the hashed password that you constructed. For example, on Debian/Ubuntu, we've been told that `useradd -m joe -s /bin/bash -p "$(mkpasswd "$password")"` might work. === Fool the computer into thinking you are a human === The second approach is to use [[https://core.tcl-lang.org/expect|Expect]] or its [[http://pexpect.sourceforge.net/pexpect.html|python equivalent]]. I think Expect even has this ''exact'' problem as one of its canonical examples. === Find some magic system-specific tool === Finally, system-specific tools designed to do this may already exist on your platform. We've already mentioned `useradd`. Some GNU/Linux systems also have a `newusers(8)` command specifically designed for this, or a `chpasswd(8)` tool which can be coerced into doing these sorts of things. Or they may have a `--stdin` flag on their `passwd` command. Also try commands such as `apropos users` or `man -k account` to see what else might exist. Be creative. See also [[BashFAQ/069|FAQ #69 -- I want to automate an ssh (or scp, or sftp) connection]]. ---- === Don't rely on /dev/tty for security === As an aside, the reverse of this FAQ is also a problem. It's trivial, at least under Linux, to wrap any program in a way that forces the controlling terminal to be an abstraction that's connected to any kind of I/O you like. This means it's very difficult to securely guarantee that a user with local access is actually giving your program input directly from a keyboard. Often people do this by reading from `/dev/tty`. This, just like the way the `passwd` program works, is only a small step to discourage bad security practices like storing passwords in plain text files. The following runs Bash, which reads a program on FD 3, which unwittingly gets its input through a pipe (which could just as easily be a file), using just one function from the Python standard library. {{{ ~ $ { echo 'o hi there' | python -c 'import pty; pty.spawn(["bash", "/dev/fd/3"])'; } <<"EOF" 3<&0- <&2 # <&2 prevents disconnecting echo's stdin. No real effect. { stty -echo read -p 'Password: ' passw printf '\npassword is: %s\n' "$passw" stty echo }