Shell script to scp rpm to remote server and install it. Needs a variable to pass remote host name - linux

I am attempting to write a sort of menu script which will achieve the below once executed:
Ask what user/password you are executing the script as.
Ask the remote server i.p. you want to scp files to.
Ask the directory where the files are stored locally.
Ask the directory where all the files are to be transferred to.
Copy all the files.
The first hurdle I have is getting the password stored as a variable within the menu. I think sshpass will be good for that. I would like to configure a menu like this:
title="Select example"
prompt="Pick an option:"
options=("A" "B" "C")
echo "$title"
PS3="$prompt "
select opt in "${options[#]}" "Quit"; do
case "$REPLY" in
1 ) echo "You picked $opt which is option $REPLY";;
2 ) echo "You picked $opt which is option $REPLY";;
3 ) echo "You picked $opt which is option $REPLY";;
$(( ${#options[#]}+1 )) ) echo "Goodbye!"; break;;
*) echo "Invalid option. Try another one.";continue;;
esac
done
But the menu would ask you for username, local directory of files, i.p. of remote server, remote server directory and then run the scp command it constructed.
Something like this:
password="your password"
username="username"
Ip="<IP>"
sshpass -p "$password" scp /<PATH>/final.txt $username#$Ip:/root/<PATH>
But I'm a bit confused as to how I can put that all of that together so that the menu gathers the required information and then executes the collected input so that it simply constructs an scp command to fire.
Can anyone offer any experience with this to aid me in the construction of the menu script?
Thanks!

You don't need a menu, just ask for each input sequentially.
read -p "Username:" username
read -s -p "Password:" password
read -p "Server IP:" ip
read -p "Local directory:" local
read -p "Remote directory" remote
sshpass -p "$password" scp "/$local/final.txt" "$username#$ip:/root/$remote/"

If you still need a menu here it is. I modified your script a bit to make it construct/print scp command while entering values one by one.
#!/bin/bash
title="Select example"
prompt="Pick an option:"
declare -A options # turn options to an associative array
options[1]='change user name'
options[2]='change user password'
options[3]='change remote host address'
options[4]='change path to source files'
options[5]='change destination path on remote server'
PS3="$prompt "
menu () { # wrap all this to a function to restart it after edition of an element
echo "$title"
select opt in "${options[#]}" "Quit"; do
case "$REPLY" in
1 ) read -p "${options[1]}: " user;;
2 ) read -sp "${options[2]}: " pass;; # read password with option -s to disable output
3 ) read -p "${options[3]}: " addr;;
4 ) read -p "${options[4]}: " from;;
5 ) read -p "${options[5]}: " dest;;
$(( ${#options[#]}+1 )) ) echo "Goodbye!" ; exit;;
*) echo "Invalid option. Try another one.";;
esac
clear # clear screen to remove inputs
printf "Creating scp command:\n"
# we don't want to show password, print *** if password set and 'password not set' if not
[[ $pass ]] && pass2='***' || pass2='[password not set]'
# text in [] will be printed if var is empty or not set, it's usefull to add default values to vars ${var:-default_value}
printf "sshpass -p $pass2 scp -r ${from:-[source not set]}/* ${user:-[user not set]}#${addr:-[host not set]}:${dest:-[destination not set]}/\n\n"
menu
done
}
clear # clear screen
menu # and start menu function
And here I've got a script with similar (but richer) functionality, please take a look.

Related

How do -s and -p alter the read command?

I'm trying to interpret this block of code. Searched google to see what these commands mean and no luck. I put my interpretation of what each line/block means to me. If I am wrong, please correct me. I am new to unix commands. Code:
#!/bin/bash
# input 1st command line argument for the version.
export VERSION=$1
# if user didn't input a version, print the echo message and exit (not sure what -n means but I am assuming)
if [[ ! -n "$VERSION" ]]; then
echo "Missing Version"
exit 1
fi
# creating variable UNAME that tells who the person is (their name)
export UNAME='whoami'
# no idea what -s and -p mean but i think this prints the message "enter password for $UNAME" and stores it in a new variable named PASSWORD. the $UNAME will print whatever whoami said.
read -s -p "Enter password for $UNAME: " PASSWORD
echo ""
The -p flag issues a prompt before reading input into a variable
The -s flag stop the typed response from being shown (i.e. for a sensitive password)
More information is available here:
https://linuxhint.com/bash_read_command/
-p
prompt output the string PROMPT without a trailing newline before
attempting to read.
-s
do not echo input coming from a terminal.

having an issue with my bash script

im writing a script that allows the user to create a backup of a file they choose by allowing them to input the file name. the file will then have backup followed by being date stamped at the end of it's name and saved on the home drive. but whenever i try to run it i get an error: cp: missing destination file operand after '_backup_2017_12_16'
here's my code:
title="my script 3"
prompt="Enter:"
options=("create a backup of a file")
echo "$title"
PS3="$prompt "
select opt in "${options[#]}" "Quit"; do
case "$REPLY" in
esac
cp "$filename""${file}_backup_$(date +%Y_%m_%d)"
done
Your case statement is currently empty. You need it to handle your chosen option
There needs to be a space between arguments: cp source dest
If you are using array for the options, you can also put Quit in there
If you choose the option to create a backup, you need to prompt the user to enter a filename. read command is used to get user input
Putting it all together, your script could look like this:
#!/usr/bin/env bash
options=("Backup" "Quit")
prompt="Enter: "
title="My script 3"
echo "$title"
PS3=$prompt
select opt in "${options[#]}"; do
case $opt in
"Backup")
IFS= read -r -p "Enter filename: " filename
cp -- "$filename" "${filename}_backup_$(date +%Y_%m_%d)" && echo "Backup created..."
;;
"Quit") break ;;
*) echo "Wrong option..." ;;
esac
done

Shell error when using multiline ssh command inside user prompt check

Running into a bit of an issue while trying to add a user prompt check to a existing script which was already working.
Here is the existing script, which is working...
#!/bin/sh
echo "**** Pulling changes into Production"
ssh user#example.com "$( cat <<'EOT'
cd example.com/html/ || exit
unset GIT_DIR
git pull
EOT
)"
Here is my modified script with a user prompt, which is broken.. and it is only broken when I add the ssh line. Works perfectly with just echoes.
#!/usr/bin/env bash
while true; do
read -p "Are you sure you want to pull changes into production? [y/N] " yn
case $yn in
[Yy]* )
ssh user#example.com "$( cat <<'EOT'
cd example.com/html/ || exit
unset GIT_DIR
git pull
EOT
)";
exit;;
[Nn]* )
echo "!!!! CANCELLING !!!!";
exit;;
* ) echo "Please answer yes or no.";;
esac
done
The error I'm getting is...
Syntax error: end of file unexpected (expecting ")")
EOT must appear at the beginning of the line. Your EOT appears somewhere in between, with lots of leading spaces.
Replace
EOT
By
EOT

ssh to different nodes using shell scripting

I am using below code to ssh to different nodes and find if an user exists or not. If the user doesn't exist it will create it.
The script works fine if I don't do ssh but it fails if I do ssh.
How can I go through different nodes using this script?
for node in `nodes.txt`
usr=root
ssh $usr#$node
do
if [ $(id -u) -eq 0 ]; then
read -p "Enter username : " username
read -s -p "Enter password : " password
egrep "^$username" /etc/passwd >/dev/null
if [ $? -eq 0 ]; then
echo "$username exists!"
exit 1
else
pass=$(perl -e 'print crypt($ARGV[0], "password")' $password)
useradd -m -p $pass $username
[ $? -eq 0 ] && echo "User has been added to system!" || echo "F
ailed to add a user!"
fi
else
echo "Only root may add a user to the system"
exit 2
fi
done
Your script has grave syntax errors. I guess the for loop at the beginning is what you attempted to add but you totally broke the script in the process.
The syntax for looping over lines in a file is
while read -r line; do
.... # loop over "$line"
done <nodes.txt
(or marginally for line in $(cat nodes.txt); do ... but this has multiple issues; see http://mywiki.wooledge.org/DontReadLinesWithFor for details).
If the intent is to actually run the remainder of the script in the ssh you need to pass it to the ssh command. Something like this:
while read -r node; do
read -p "Enter user name: " username
read -p -s "Enter password: "
ssh root#"$node" "
# Note addition of -q option and trailing :
egrep -q '^$username:' /etc/passwd ||
useradd -m -p \"\$(perl -e 'print crypt(\$ARGV[0], \"password\")' \"$password\")" '$username'" </dev/null
done <nodes.txt
Granted, the command you pass to ssh can be arbitrarily complex, but you will want to avoid doing interactive I/O inside a root-privileged remote script, and generally make sure the remote command is as quiet and robust as possible.
The anti-pattern command; if [ $? -eq 0 ]; then ... is clumsy but very common. The purpose of if is to run a command and examine its result code, so this is better and more idiomatically written if command; then ... (which can be even more succinctly written command && ... or ! command || ... if you only need the then or the else part, respectively, of the full long-hand if/then/else structure).
Maybe you should only do the remote tasks via ssh. All the rest runs local.
ssh $user#$node egrep "^$username" /etc/passwd >/dev/null
and
ssh $user#$node useradd -m -p $pass $username
It might also be better to ask for username and password outside of the loop if you want to create the same user on all nodes.

How do I search for a certain piece of text inside of a variable?

I am working on a script which prompts the user for their username. Once entered, the script uses the 'rwho' command to get a list of users who are logged into the network. It should crosscheck the text they entered (their username) with the results from the rwho command.
If a match is found then it displays a message saying so, if not then it also makes the user aware of this.
Here is the script and my attempt so far:
#!/bin/sh
#
# User network checking script
#
# Using rwho command to get user list
OUTPUT="$(rwho)"
echo "${OUTPUT}"
# Prompt for username
echo "Please enter your username: "
read username
# Input validation
if [ -z "$username"]
then
echo "No username supplied"
echo "Please enter your username: "
read username
fi
# Search for user
if `echo ${OUTPUT} | grep "${username}" 1>/dev/null 2>&1'
then
echo "$username is logged in."
else
echo "$username is not present."
fi
I consistently get errors with the Search for User part. I don't have outstanding knowledge of Linux so if anyone could fix this and help me I would be greatly appreciative.
Your usage of quotes is weird.
if echo "$OUTPUT" | grep -q "$username"
should work.
-q makes grep quiet (and is shorter than your redirections).

Resources