Exporting a variable with a backslash - bash

I am working on an install script, of the following form:
# get username
echo "Please enter your oracle username:"
read -p "> " username
stty -echo
# get password
echo "Please enter your oracle password:"
read -r -p "> " password; echo
stty echo
# -- Create all text to output to config
finaluser=$usernamelabel$username
finalpassword=$passwordlabel$password
echo -e $finaluser"\n"$finalpassword > $configfile
The problem is, if a password of the form like 'z\2z', it is outputted to $configfile as:
z^Bz
Is there any easy way to avoid this?

Don't embed the \n, and then you don't need the -e option which is also interpreting the \2.
echo "$finaluser" >$configfile
echo "$finalpassword" >>$configfile
or
cat >$configfile <<EOF
$finaluser
$finalpassword
EOF
or a third way if you really want to use a single command
printf '%s\n%s\n' "$finaluser" "$finalpassword"

Related

how to replace special character in linux variables

#!/bin/bash
read -p "Please Enter you OS Password:" PASSWORD
echo "the password is $PASSWORD"
input: Test$1234
We want the output as Test\$1234
You can use printf "%q" $PASSWORD to "shell-escape" the contents of $PASSWORD. This does not only take care of $, but also other special shell characters, such as !, &, >, etc.
#!/bin/bash
read -p "Please Enter you OS Password:" PASSWORD
PASSWORD=$(printf "%q" $PASSWORD)
echo "the password is $PASSWORD"
You can try with the below command, here sed command will replace $ with \$ and will not replace any other special character so no side effect:-
!/bin/bash
read -p "Please Enter you OS Password:" PASSWORD
PASSWORD=$(echo $PASSWORD |sed 's/\$/\\$/g')
echo "the password is $PASSWORD"

Expect Script for CLI

UPDATE: I am really frustrated at this point. I've tried moving the expect code to its own file and calling it from the bash script.
...
if [[ "$okay" == "OK" ]]
then
echo "PASSWORD ACCEPTED"
echo "Modifying User Passwords..."
COUNTER=0
while [ $COUNTER -lt $num ]; do
let index=COUNTER+1
tmp=user_$index
echo "Changing Password for " ${!tmp}
tmp2=$(${!tmp})
echo $tmp2
sh ./input.sh ${current_user} ${pass} ${password} ${tmp2}
let COUNTER=COUNTER+1
done
...
input.sh
expect -f
#------------------------------------------------------
set current_user [lindex $argv 0]
set pass [lindex $argv 1]
set password [lindex $argv 2]
set tmp2 [lindex $argv 3]
echo "EXPECT SCRIPT RUNNING"
sudo passwd ${!tmp2}
expect -exact "[sudo] password for $current_user: "
send "$pass\r"
expect -exact "New password: "
send "$password\r"
I would greatly, greatly appreciate it if someone could help me out.
I am writing a script that will allow a Linux admin to quickly change passwords of its users.
#!/usr/bin/expect
# Check password for strength
# ----------------------------------------------
read -p "What's your username?" current_user
read -p "What's the root password?" pass
read -p "How many users?" num
COUNTER=0
while [ $COUNTER -lt $num ]; do
let index=COUNTER+1
read -p "Enter username$index : " user_$index
let COUNTER=COUNTER+1
done
read -p "Enter password : " password
echo
echo "Tesing password strength..."
echo
result="$(cracklib-check <<<"$password")"
okay="$(awk -F': ' '{ print $2}' <<<"$result")"
if [[ "$okay" == "OK" ]]
then
echo "PASSWORD ACCEPTED"
echo "Modifying User Passwords..."
COUNTER=0
while [ $COUNTER -lt $num ]; do
let index=COUNTER+1
tmp=user_$index
echo "Changing Password for " ${!tmp}
echo ${!tmp}
sudo passwd ${!tmp}
expect -exact "[sudo] password for $current_user: "
send "$pass\r"
expect -exact "New password: "
send "$password\r"
let COUNTER=COUNTER+1
done
#echo "$user:$password" | usr/sbin/chpasswd
else
echo "Your password was rejected - $result"
echo "Try again."
fi
However, the expect portion, which would automate the inputting of passwords, is not highlighted in my editor and does not work. I keep getting prompts to manually enter text. This is especially surprising since the script is sourcing expect, not bash. I've been trying to fix this for the past 2 hours. Can anyone please lend me a hand?
I see some issues in your code. At first, you have tried adding #!/usr/bin/expect in the code, which should throw you an error about the read command as,
wrong # args: should be "read channelId ?numChars?" or "read ?-nonewline? channelId"
while executing
"read -p "What's your username?" current_user"
The reason is simply because the script will be treated as Expect script and it is not following it's syntax for read. I wonder how it worked for you. :)
When it is called as shell script, in that it should be enclosed withing expect -c not simply with expect -f
When expect -c is enclosed with single quotes, it won't allow bash substitutions. So, I am going to use double quotes. (but, it we have to escape the Expect's double quotes with backslashes.)
admin="dinesh"
admin_pwd="root"
user="satheesh"
user_pwd="Hello#12E"
OUTPUT=$(expect -c "
# To suppress any other form of output generated by spawned process
log_user 0
spawn sudo passwd $user
expect {
timeout { send_user \"Timeout happened\n\";exit 0}
\"Sorry, try again\" {send_user \"Incorrect admin password\";exit 0}
\"password for $admin: $\" {send \"$admin_pwd\r\";exp_continue}
\"password: $\" {send \"$user_pwd\r\";exp_continue}
\"successfully\" {send_user \"Success\"; exit 1}
}
")
echo "Expect's return value : $?"
echo "-----Expect's response-----"
echo $OUTPUT
The Expect's return value will be available in the variable $?. This will help us to know whether the password update is successful or not. The variable OUTPUT, will have the output generated by spawned process.
Use the #!/bin/bash, not #!/usr/bin/expect, since it is actually a bash script.

BASH - Function to get user password

I created the following BASH script that works perfectly for getting a password from the user:
while [ -z "$PASSWORD" ]
do
echo "Please enter a password:"
read -s PASSWORD1
echo "Please re-enter the password to confirm:"
read -s PASSWORD2
if [ "$PASSWORD1" = "$PASSWORD2" ]; then
PASSWORD=$PASSWORD1
else
# Output error message in red
red='\033[0;31m'
NC='\033[0m' # No Color
echo ""
echo -e "${red}Passwords did not match!${NC}"
fi
done
# This is just here to prove script works
echo "password is: $PASSWORD"
However, if I place it in a function, it stops working:
function getPasswordFromUser()
{
while [ -z "$PASSWORD" ]
do
echo "Please enter a password:"
read -s PASSWORD1
echo "Please re-enter the password to confirm:"
read -s PASSWORD2
if [ "$PASSWORD1" = "$PASSWORD2" ]; then
PASSWORD=$PASSWORD1
else
# Output error message in red
red='\033[0;31m'
NC='\033[0m' # No Color
echo ""
echo -e "${red}Passwords did not match!${NC}"
fi
done
echo $PASSWORD
}
PASSWORD=$(getPasswordFromUser)
# This is just here to check if script worked
echo "got password $PASSWORD"
If I change the call to the function from PASSWORD=$(getPasswordFromUser) to: getPasswordFromUser; then the method starts "working" but the password is output to the screen, and I haven't captured it.
Is there a way to update this BASH script so that I can call a function to get a password from the user without the password ever being displayed in the terminal?
In case it matters, this is for Debian/Ubuntu.
If you call the function like myvar=$(myfunction) it will catch the first echo statement.
What you can do, instead, is to define a variable within the function and then access it. There is no scope in bash, so you will be able to access it once the function has been executed.
See an example on each one of them:
$ cat a
#!/bin/bash
function myf()
{
echo "heeeiiii"
echo "hellO"
}
function myf2()
{
echo "lets define var MYTEST"
MYTEST="this is my test"
}
r=$(myf)
echo "this is myf: $r"
echo "MYTEST=$MYTEST"
myf2
echo "MYTEST=$MYTEST"
Execution:
$ ./a
this is myf: heeeiiii
hellO
MYTEST=
lets define var MYTEST
MYTEST=this is my test
Most of the output in your function should be written to standard error, not standard output.
getPasswordFromUser()
{
while [ -z "$PASSWORD" ]
do
echo "Please enter a password:" >&2
read -s PASSWORD1
echo "Please re-enter the password to confirm:" >&2
read -s PASSWORD2
if [ "$PASSWORD1" = "$PASSWORD2" ]; then
PASSWORD=$PASSWORD1
else
# Output error message in red
red='\033[0;31m'
NC='\033[0m' # No Color
echo -e "\n${red}Passwords did not match!${NC}" >&2
fi
done
echo "$PASSWORD"
}
Also, be sure to quote $PASSWORD in the final line; someone may use multiple runs of whitespace or shell glob characters in their password!
Your first attempt is correct:
~$ PASSWORD=$(getPasswordFromUser)
~$ echo $PASSWORD
Please enter a password: Please re-enter the password to confirm: a
You just don't see the "Please enter a password" because it is captured by the $(..).
You have several possibilities:
use a global variable
use different descriptor
have the function take a variable as the first arg and modify the variable with the string you want to return.
Some examples can be found in how to return a string value from a bash function, the Advanced Bash-Scripting Guide, or the linux journal.

How to call a bash script from another script?

I have two very simple scripts. I have asked this question but people thought I am doing it in different platform. Actually these two scripts are in same folder.
One is source.sh
#!/bin/bash
echo "start"
./call.sh
echo "end"
And second is call.sh
#!/bin/bash
passDir="/etc/passwd"
while read line
do
while true
do
echo "prompt"
#propmt for username
read -p "Enter username : " username
egrep "^$username" $passDir >/dev/null
if [ $? -eq 0 ]; then
echo "$username exists!"
else
userName=$username
break
fi
done
done < user.txt
and user.text file is only two words in two lines
Hello
world
Output:
exisats!
prompt
exisats!
prompt
exisats!
prompt
exisats!
prompt
exisats!
prompt
exisats!
prompt
Until I press Ctrl+d I really appreciate if anyone can tel how I can fix this.
You can reduce this to a minimal example:
#!/bin/bash
while read line
do
echo line is $line
echo "prompt"
read -p "Enter username : " username
echo username is $username
done < user.txt
Now the problem is clear: the script reads everything from user.txt.
Only read should read from user.txt. We can tell read to do this by means of a file descriptor:
#!/bin/bash
exec 3< user.txt # open the file, give it File Descriptor 3
while read -r -u3 line
do
echo line is $line
echo "prompt"
read -p "Enter username : " username
echo username is $username
done
exec 3<&- # close the file

Until user input equals something do

So somebody showed me how to use condition(s) to test if a user had typed input for a password.
I wanna take a their example a step further and use a loop (at least thats what I think it's call).
Here is their example:
read -s -p "Enter new password: " NEWPASS
if test "$NEWPASS" = ""; then
echo "Password CAN NOT be blank re-run sshd_config"
exit 1;
fi
Instead of exiting the script I want it to keep asking for the input until there is some.
I wanna make a statement like this but I was doing it wrong:
(Now using top example)
The user is given a chance to enter new password and fill the variable value.
read -s -p "Enter new password:" NEWPASS
echo ""
The next portion checks the variable to see if it contains a value, while the value is null it request the user to fill the value indefinitely. ( a loop)
while [[ -z "$NEWPASS" ]]; do
echo ""
echo "Password CAN NOT be blank"
echo ""
read -s -p "Enter new password:" NEWPASS;
echo ""
done
This line searches a file containing a set of variables used by another file. It then searches the file for a line containing PASS=.* (.* meaning anything) then writes PASS=$NEWPASS ($NEWPASS being variable)
sed -i -e"s/^PASS=.*/PASS=$NEWPASS/" /etc/sshd.conf
Thank you for all the help, I'm going to use this and learn from it.
This while loop should work:
while [[ -z "$NEWPASS" ]]
do
read -s -p "Enter new password: " NEWPASS
done
while read -s -p 'Enter new password: ' NEWPASS && [[ -z "$NEWPASS" ]] ; do
echo "No-no, please, no blank passwords!"
done

Resources