How to send input to a program using sh script - bash

I wrote a script that I thought would send input to the terminal when the program request input. I use echo for this.
password=open1234
for I in "a" "b" "c" "d" "e" "f" "g"
do
passwd ${I}
echo ${password}
done
This is basically the form of the program. As you can see, i'm trying to change the passwords of multiple users using a script. The problem is that the input from echo never gets sent to the passwd program.

As written here, you must add --stdin option to passwd.
echo "${password}" | passwd "${I}" --stdin

simply use(It would change all users to the same password):
#!/bin/bash
script='
passwd $user <<PASS
open1234
open1234
PASS
'
for user in $(cat user.txt)
do
$script
done

Related

How to use encrypted password with sftp login?

I want to write a shell script where user interaction is not allowed and I want to use sftp login with in the script. Now I have few challenges to execute this approach.
There is no user interaction so I can only provide the options as a argument while executing the script. Script can be like this.
#!/bin/bash
if [[ "${#}" -lt 4 ]]; then
echo -e "Usage: ${0} <sftpUser> <sftpPassword> <sftpHost> <sftpPort>"
exit 1
fi
sftpUser=${1}
sftpPassword=${2}
sftpHost=${3}
sftpPort=${4}
remote_dir="/home/vagrant"
source_dir="/home/vagrant/sftpDir"
sftpFile="/tmp/tempfile"
echo "cd ${remote_dir}" >> ${sftpFile}
echo "mget * ${source_dir}" >> ${sftpFile}
echo "quit" >> ${sftpFile}
expect -c "
spawn sftp -P ${sftpPort} -o "BatchMode=no" -b "${sftpFile}" ${sftpUser}#${sftpHost}
expect -nocase \"*Password:\" { send \"${sftpPassword}\r\"; interact }
"
rm -rf ${sftpFile}
$ ./shellscript.sh user1 password#123 192.168.0.1 22
Here, we need to provide the argument with the script itself and here we are using the plain text format for password password#123
How can we use the encrypted password in the argument as this can be a risk to expose the password?
Is there any other approach to execute this scenario?
I am not able to find any approach to pass the encrypted password with SFTP login.

How to fix chpasswd: line 5: missing new password error [duplicate]

I need to have the ability to create user accounts on my Linux (Fedora 10) and automatically assign a password via a bash script(or otherwise, if need be).
It's easy to create the user via Bash e.g.:
[whoever#server ]# /usr/sbin/useradd newuser
Is it possible to assign a password in Bash, something functionally similar to this, but automatically:
[whoever#server ]# passwd newuser
Changing password for user testpass.
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.
[whoever#server ]#
You could also use chpasswd:
echo username:new_password | chpasswd
so, you change password for user username to new_password.
You can run the passwd command and send it piped input. So, do something like:
echo thePassword | passwd theUsername --stdin
I was asking myself the same thing, and didn't want to rely on a Python script.
This is the line to add a user with a defined password in one bash line:
useradd -p $(openssl passwd -crypt $PASS) $USER
The code below worked in Ubuntu 14.04. Try before you use it in other versions/linux variants.
# quietly add a user without password
adduser --quiet --disabled-password --shell /bin/bash --home /home/newuser --gecos "User" newuser
# set password
echo "newuser:newpassword" | chpasswd
I liked Tralemonkey's approach of echo thePassword | passwd theUsername --stdin though it didn't quite work for me as written. This however worked for me.
echo -e "$password\n$password\n" | sudo passwd $user
-e is to recognize \n as new line.
sudo is root access for Ubuntu.
The double quotes are to recognize $ and expand the variables.
The above command passes the password and a new line, two times, to passwd, which is what passwd requires.
If not using variables, I think this probably works.
echo -e 'password\npassword\n' | sudo passwd username
Single quotes should suffice here.
The following works for me and tested on Ubuntu 14.04. It is a one liner that does not require any user input.
sudo useradd -p $(openssl passwd -1 $PASS) $USERNAME
Taken from #Tralemonkey
Single liner to create a sudo user with home directory and password.
useradd -m -p $(openssl passwd -1 ${PASSWORD}) -s /bin/bash -G sudo ${USERNAME}
You can use the -p option.
useradd -p encrypted_password newuser
Unfortunately, this does require you to hash the password yourself (where passwd does that for you). Unfortunately, there does not seem to be a standard utility to hash some data so you'll have to write that yourself.
Here's a little Python script I whipped up to do the encryption for you. Assuming you called it pcrypt, you would then write your above command line to:
useradd -p $(pcrypt ${passwd}) newuser
A couple of warnings to be aware of.
While pcrypt is running, the plaintext will be visible to any user via the ps command.
pcrypt uses the old style crypt function - if you are using something more moderns like an MD5 hash, you'll need to change pcrypt.
and here's pcrypt:
#!/usr/bin/env python
import crypt
import sys
import random
saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
def salt():
return random.choice(saltchars) + random.choice(saltchars)
def hash(plain):
return crypt.crypt(arg, salt())
if __name__ == "__main__":
random.seed()
for arg in sys.argv[1:]:
sys.stdout.write("%s\n" % (hash(arg),))
--stdin doesn't work on Debian. It says:
`passwd: unrecognized option '--stdin'`
This worked for me:
#useradd $USER
#echo "$USER:$SENHA" | chpasswd
Here we can find some other good ways:
http://www.debian-administration.org/articles/668
You can use expect in your bash script.
From http://www.seanodonnell.com/code/?id=21
#!/usr/bin/expect
#########################################
#$ file: htpasswd.sh
#$ desc: Automated htpasswd shell script
#########################################
#$
#$ usage example:
#$
#$ ./htpasswd.sh passwdpath username userpass
#$
######################################
set htpasswdpath [lindex $argv 0]
set username [lindex $argv 1]
set userpass [lindex $argv 2]
# spawn the htpasswd command process
spawn htpasswd $htpasswdpath $username
# Automate the 'New password' Procedure
expect "New password:"
send "$userpass\r"
expect "Re-type new password:"
send "$userpass\r"
I know I'm coming at this years later, but I can't believe no one suggested usermod.
usermod --password `perl -e "print crypt('password','sa');"` root
Hell, just in case someone wants to do this on an older HPUX you can use usermod.sam.
/usr/sam/lbin/usermod.sam -F -p `perl -e "print crypt('password','sa');"` username
The -F is only needed if the person executing the script is the current user. Of course you don't need to use Perl to create the hash. You could use openssl or many other commands in its place.
I've tested in my own shell script.
$new_username means newly created user
$new_password means newly password
For CentOS
echo "$new_password" | passwd --stdin "$new_username"
For Debian/Ubuntu
echo "$new_username:$new_password" | chpasswd
For OpenSUSE
echo -e "$new_password\n$new_password" | passwd "$new_username"
Here is a script that will do it for you .....
You can add a list of users (or just one user) if you want, all in one go and each will have a different password. As a bonus you are presented at the end of the script with a list of each users password. .... If you want you can add some user maintenance options
like:
chage -m 18 $user
chage -M 28 $user
to the script that will set the password age and so on.
=======
#!/bin/bash
# Checks if you have the right privileges
if [ "$USER" = "root" ]
then
# CHANGE THIS PARAMETERS FOR A PARTICULAR USE
PERS_HOME="/home/"
PERS_SH="/bin/bash"
# Checks if there is an argument
[ $# -eq 0 ] && { echo >&2 ERROR: You may enter as an argument a text file containing users, one per line. ; exit 1; }
# checks if there a regular file
[ -f "$1" ] || { echo >&2 ERROR: The input file does not exists. ; exit 1; }
TMPIN=$(mktemp)
# Remove blank lines and delete duplicates
sed '/^$/d' "$1"| sort -g | uniq > "$TMPIN"
NOW=$(date +"%Y-%m-%d-%X")
LOGFILE="AMU-log-$NOW.log"
for user in $(more "$TMPIN"); do
# Checks if the user already exists.
cut -d: -f1 /etc/passwd | grep "$user" > /dev/null
OUT=$?
if [ $OUT -eq 0 ];then
echo >&2 "ERROR: User account: \"$user\" already exists."
echo >&2 "ERROR: User account: \"$user\" already exists." >> "$LOGFILE"
else
# Create a new user
/usr/sbin/useradd -d "$PERS_HOME""$user" -s "$PERS_SH" -m "$user"
# passwdgen must be installed
pass=$(passwdgen -paq --length 8)
echo $pass | passwd --stdin $user
# save user and password in a file
echo -e $user"\t"$pass >> "$LOGFILE"
echo "The user \"$user\" has been created and has the password: $pass"
fi
done
rm -f "$TMPIN"
exit 0
else
echo >&2 "ERROR: You must be a root user to execute this script."
exit 1
fi
===========
Hope this helps.
Cheers,
Carel
The solution that works on both Debian and Red Hat. Depends on perl, uses sha-512 hashes:
cat userpassadd
#!/usr/bin/env bash
salt=$(cat /dev/urandom | tr -dc A-Za-z0-9/_- | head -c16)
useradd -p $(perl -e "print crypt('$2', '\$6\$' . '$salt' . '\$')") $1
Usage:
userpassadd jim jimslongpassword
It can effectively be used as a one-liner, but you'll have to specify the password, salt and username at the right places yourself:
useradd -p $(perl -e "print crypt('pass', '\$6\$$salt\$')") username
From IBM (https://www.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.cmds1/chpasswd.htm):
Create a text file, say text.txt and populate it with user:password pairs as follows:
user1:password1
user2:password2
...
usern:passwordn
Save the text.txt file, and run
cat text.txt | chpassword
That's it. The solution is (a) scalable and (b) does not involve printing passwords on the command line.
Tralemonkey's solution almost worked for me as well ... but not quite. I ended up doing it this way:
echo -n '$##password##$' | passwd myusername --stdin
2 key details his solution didn't include, the -n keeps echo from adding a \n to the password that is getting encrypted, and the single quotes protect the contents from being interpreted by the shell (bash) in my case.
BTW I ran this command as root on a CentOS 5.6 system in case anyone is wondering.
{ echo $password; echo $password; } | passwd $username
For RedHat / CentOS here's the code that creates a user, adds the passwords and makes the user a sudoer:
#!/bin/sh
echo -n "Enter username: "
read uname
echo -n "Enter password: "
read -s passwd
adduser "$uname"
echo $uname:$passwd | sudo chpasswd
gpasswd wheel -a $uname
usage: ./my_add_user.sh USER PASSWD
code:
#!/bin/bash
# my_add_user.sh
if [ "$#" -lt 2 ]
then
echo "$0 username passwd"
exit
fi
user=$1
passwd=$2
useradd $user -d /data/home/$user -m ;
echo $passwd | passwd $user --stdin;
Kindly run below script with sudo permission for creating a user by script.
Note: This script supports all linux OSs like Redhat, Centos, Ubuntu, suse, kali, Arch, Bitname, BSD....etc
#!/bin/bash
#author: bablish jaiswal
#purpos: Linux user creation with a storng password
clear
#echo "Hi, I am a function to create sudo user with strong password. Kindly share following information"
echo -e "\n\n\n"
printf "\e[6;33mHi, I am a function to create sudo user with a strong password. Kindly share following information\e[0m";echo
read -p "user name:- " name #input name
read -p "complete path for $name home directory? example: /home/$name :- " home #user home path
( useradd -m -d $home $name -s /bin/bash ) > /dev/null 2>&1
pass=$(cat /dev/urandom |tr -dc "[[:graph:]]" |head -c16)
(echo -e "$pass\n$pass" | passwd $name ) > /dev/null 2>&1
echo " "
printf "\e[6;33m-----------------------------Copy below credentials-------------------------\e[0m";echo
echo -e "User:- $name\nHomeDir:- $home\npassword:- $pass"
#svalue=$(cat /etc/sudoers |grep -i root |grep -i all|tail -n1 |awk '{$1=""}1')
svalue=$(cat /etc/sudoers |grep -i root |grep -i all|tail -n1 |awk '{print $2}')
echo "${name} ${svalue} NOPASSWD:ALL" >> /etc/sudoers && echo “Remark:- User $name is a sudo user”

Batch Script Error - unexpected end of file

I'm trying to run a task where I have a script that will add a user to a remote server via ssh.
Here is my code:
#echo off
setlocal enabledelayedexpansion
set username=%1
set password=%2
for /F "tokens=*" %%a in (Linuxhosts.txt) do (
ssh -i svcaccount_id_rsa svcaccount#%%a 'bash -s' < adduser.txt
)
Here are the contents of the adduser.txt file
#!/bin/bash
#========================================================================================================
# This script allows for account creation on a server |
# It also performs error handling to ensure that the user doesn't currently exist on the system. |
# Also provides feedback from the input to verify the entries are correct. |
#========================================================================================================
while true; do
echo -n "Enter username: "
read -r username
/bin/egrep -i "^${username}:" /etc/passwd
if [ $? -eq 0 ]; then
echo "User $username already exists. Please check the username and try again."
else
echo "User $username does not exist. Proceed with account creation."
break
fi
done
adduser "$username"
if [ $? -gt 0 ]; then
echo "Error encountered."
exit 1
fi
echo -n "Enter password: "
read -r -s password
echo "$username:$password" | chpasswd
echo "Password was succesfully set for $username."
if [ $? -gt 0 ]; then
echo "Error encountered. There was a problem with your entry. Please re-run the script and try again."
exit 1
fi
usermod -a -G wheel "$username"
echo "User was succesfully added to the group wheel."
if [ $? -gt 0 ]; then
echo "Error encountered."
exit 1
fi
echo "Successfully added $username to the system."
However, when I try to run the first set of code through a cmd prompt, I get the following error:
bash: line 41: syntax error: unexpected end of file
I'm not sure what I'm missing. I have tested it with another file called hello.txt and it ran fine so I'm wondering if maybe there's spacing issues somewhere that I can't see because it's a text file.
I'm pretty sure the immediate problem here is that the file adduser.txt is in DOS/Windows format, with its lines terminated with a carriage return character, followed by a linefeed. Unix (including bash) expects just a linefeed as the line terminator, and hence treats the carriage return as part of the line's text. In this case, that means that bash sees line 17, "done", as "done[carriage return]" which isn't a valid keyword and does not end the while loop, so it keeps looking for the "done" keyword... until it runs out of file.
(Credit to Squashman for suggesting this in a comment.)
You're likely to have this problem a lot transferring files from Windows to unix; unfortunately, the tools available to fix the problem vary quite a bit depending on what OS you're using, etc.
BTW, I see a couple of other problems here. For one thing, the read commands in the script are going to be trying to read from the same source that bash is reading commands from, which is the adduser.txt file. So when it does e.g. read -r username it's actually going to be reading some later line from the script file, not from the user running the batch script. This is going to be very hard to solve the way you're doing it; I think it'll be much better to actually copy the script file to the unix system, then run it separately.
Also, as Socowi pointed out in the comments, $? gets the exit status of the last command executed, so in sections like this:
echo "$username:$password" | chpasswd
echo "Password was succesfully set for $username."
if [ $? -gt 0 ]; then
...
the if condition is checks the exit status of the command echo "Password was succesfully set for $username.", not the chpasswd command. The same problem applies to the usermod command later. The better way to do this is to use the command you want to check for success directly as the if condition:
if echo "$username:$password" | chpasswd; then
echo "Password was succesfully set for $username."
else
echo "Error encountered. There was a problem with your entry. Please re-run the script and try again."
exit 1
fi
I'd use this same format in all of the places you're checking exit status: the egrep, useradd, chpasswd, and usermod commands.
[UPDATE] After a bit of mulling, I have a couple of possible solutions: First, to fix the carriage return problem, you could pipe the file through tr -d "\r" as a quick-n-dirty CR remover (although you may have to play around with the quoting and/or escaping to get that \r through both batch and bash's command processing). Second, pass the username and password as arguments to the script instead of having it read them. Thus, your batch script would use something like this:
ssh -i svcaccount_id_rsa svcaccount#%%a 'tr -d "\r" | bash -s "username" "password"' < adduser.txt
... then change adduser.txt to use username="$1"; password="$2" instead of the read commands (and also changing that while loop into an if, since there wouldn't be an option to try again with a different username).

ssh bash receive variable from a remote file

I need to read the variable from a remote file over SSH and compare it. But I get a variable in the wrong format. how to do it correctly?
#!/bin/bash
pass='dpassspass'
user='root#10.10.19.18'
IP="10.2.1.41"
path=/sys/variable/serv
#not work## No such file or directory# write=$(sshpass -p $ovhpass ssh -t $user echo "$IP" > $path)
sshpass -p $pass ssh -t $user << EOF
echo "$IP" > $path
EOF
my_var=$(sshpass -p $pass ssh -t $user "cd /sys_ovh; ./serv.bash")
echo mystart-"$my_var"-myend
read=$(sshpass -p $pass ssh -t $user cat $path)
echo start-"$read"-end
echo start-"$IP"-end
if [ "$read" == "$IP" ]; then
echo "run"
fi
output:
Connection to 10.10.19.18 closed.
-myendt-10.2.1.41
Connection to 10.10.19.18 closed.
-endt-10.2.1.41
start-10.2.1.41-end
Where I make a mistake? How to take data from the SSH?
The vars my_var and read are filled with a string ending with '\r', telling echo to go back to the first column. I think this is a problem with your local script. You can correct that with
tr -d "\r" < myfile > myfile2
Your fundamental problem comes from using unquoted here documents for the commands. You should properly understand in which order the shell interprets these contructs.
ssh remote cmd >file
executes cmd remotely, but first redirects the output from the ssh command to the local file.
ssh remote "cmd >’$file'"
The quotes cause the redirection to be part of the remote command line. The variable file is interpreted first, by the local shell, though.
ssh remote 'cmd >"$file"`
The single quotes prevent the local shell from modifying the command before sending it. Thus, he variable interpolation and the redirection are both handled by the remote shell, in this order.
So your commented-out "not work" command could easily be fixed with proper quoting. However, it will be much more elegant and efficient to use a single remote session, and execute all the commands in one go. Mixing the local variable IP with remote variables calls for some rather elaborate escaping, though. A major simplification would be to pass the value on standard input, so that the entire remote script can be single quoted.
#!/bin/bash
pass='dpassspass'
user='root#10.10.19.18'
IP="10.2.1.41"
result=$(echo "$IP" |
sshpass -p "$pass" ssh -t "$user" '
path=/sys/variable/serv
cat > "$path"
cd /sys_ovh
./serv.bash
cat "$path"')
echo mystart-"${result%$'\n'*}"-myend
echo start-"${result#*$'\n'}"-end
echo start-"$IP"-end
if [ "${result#*$'\n'}" == "$IP" ]; then
echo "run"
fi
The output from the remote shell is two lines; we pick it apart by using the shell's prefix and suffix substitution operators.

BASH: sending commands to ftp and validating status codes

I want to write a bash script that runs ftp on background. I want to some way send commands to it and receive responses. For example a want run ftp, then sent it
user username pass
cd foo
ls
binary
mput *.html
and receive status codes and verify them. I tried to do it this way
tail -n 1 -f in | ftp -n host >> out &
and then reading out file and verifying. But it doesn't work. Can somebody show me the right way? Thanks a lot.
I'd run one set of commands, check the output, and then run the second set in reaction to the output. You could use here-documents for the command sets and command substitution to capture the output in a variable, e.g. like this:
output=$(cat <<EOF | ftp -n host
user username pass
cd foo
ls
binary
mput *.html
EOF
)
if [[ $output =~ "error message" ]]; then
# do stuff
fi

Resources