Respond to a prompt in a shell script - shell

I am learning to write bash scripts when I ran across this doubt. Have a look at the script below. It is not the actual script but is perfect to put my point.
#!/bin/bash
firstName = "Tony"
lastName = "Stark"
init
#The command prompts here:
# > Hello!
# > bla blah
# > What is your name?
echo firstName
# > bla blah
# > Now you may enter your last name
echo lastName
Problem: So what I want to achieve is to echo only when the command prompts for What is your name?. I want to wait until prompt asks this specific question and then echo the stuff automatically. I am trying to automate this data using the script.
I tried the read command but it didn't work as thought. Is there a good way to do it? Anybody willing to shed some light is greatly appreciated. Thanks in advance!
Edit: Consider this for an instance. Please don't look at the security risks for this example. Lets automate git push.
#!/bin/bash
username: "un"
password: "pd"
git add -A
git commit -m "Update"
# returns a commit message in a second or so. It can throw an error. So `read` can not know how many lines to read. Execute the next command after reading whatso ever is the result(for now)
read message #ignore whatever the message is
git push origin master
# Now it asks for username. What I want is to echo the username on when it outputs: `Username for 'https://github.com':`
echo username
# Asks `Password for un:`
echo password
I know it has many security and functional loopholes. But I want to know is the particular way to automate echoing after a specific question is asked.

Related

Using Expect to fill a password in a bash script

I am relatively new to working in bash and one of the biggest pains with this script I have to run is that I get prompted for passwords repeatedly when running this script. I am unable to pass ssh keys or use any options except expect due to security restrictions but I am struggling to understand how to use expect.
Does Expect require a separate file from this script to call itself, it seems that way looking at tutorials but they seem rather complex and confusing for a new user. Also how do I input into my script that I want it to auto fill in any prompt that says Password: ? Also this script runs with 3 separate unique variables every time the script is called. How do I make sure that those are gathered but the password is still automatically filled?
Any assistance is greatly appreciated.
#!/bin/bash
zero=`echo $2`
TMPIP=`python bin/dgip.py $zero`
IP=`echo $TMPIP`
folder1=`echo $zero | cut -c 1-6`
folder2=`echo $zero`
mkdir $folder1
cd $folder1
mkdir $folder2
cd $folder2
scp $1#`echo $IP`:$3 .
Embedding expect code in an shell script is not too difficult. We have to be careful to get the quoting correct. You'll do something like this:
#!/usr/bin/env bash
user=$1
zero=$2
files=$3
IP=$(python bin/dgip.py "$zero")
mkdir -p "${zero:0:6}/$zero"
cd "${zero:0:6}/$zero"
export user IP files
expect <<<'END_EXPECT' # note the single quotes here!
set timeout -1
spawn scp $env(user)#$env(IP):$env(files) .
expect {assword:}
send "$env(my_password)\r"
expect eof
END_EXPECT
Before you run this, put your password into your shell's exported environment variables:
export my_password=abc123
bash script.sh joe zero bigfile1.tgz
bash script.sh joe zero bigfile2.tgz
...
Having said all that, public key authentication is much more secure. Use that, or get your sysadmins to enable it, if at all possible.

Bash Script Help "if (user input) = then (var) ="

I a writing a script to cherry pick all open changes from Gerrit. I found one that works sort of, though I need to be able to change inputs so that I do not have a script for each repo hardcoded with that specific repo's information.
#! /bin/sh
REMOTE="${1-review}"
ssh -p 29418 user#gerrit.remote.com gerrit query --format=text --patch-sets status:open branch:XXX project:XXX | grep revision: | awk '{print $2;}' | while read ID
do
git fetch "${REMOTE}" && git cherry-pick "${ID}"
done
Now I have been able to pick open changes successfully but I am trying to make it so I can pass input to change username, branch, project and remote. With the current method I need to enter my username, project, branch, and remote manually into the script. Then it is only good for that specific repo.
I have been having trouble with if/then statements. I know as it looks now none of the things I am asking for are coded, I wanted to provide someone with a working model though.
I did change username and the particular details, easy enough for someone to use this script themselves to cherry-pick by inserting the requisite information.
If I do something like this:
PROJECT="$1"
if [ "$1" = "XX" ]; then
"$PROJECT="project:name of project"
Then bash returns XX command not found. I am not trying to make it a command I want it to be input to be inserted into the ssh command later on. Also I am trying to not only use if but also else if so that PROJECT can be whatever is input.
I think I am almost there though completely stumped at this point.
Assume $1 is equal to "XX". Your code:
PROJECT="$1"
will assign PROJECT=XX. Next,
if [ "$1" = "XX" ]; then
is true, "then" clause will be executed. This clause is:
"$PROJECT="project:name of project"
that tries to execute command "XX=...", causing "command not found"
Suggestion, remove $ on this line, as in:
PROJECT="project:name of project"

bash overriding a single line in a text file with another while using variables

Overview: I am trying to make a script that will take a list of machines and manually update their /etc/shadow files with a new root passwd. I know this isn't the best method but my boss wants this process automated. we are using a application called puppet for 90% of the update but some machines failed the update or can't have puppet installed, hence this dodgy fix.
(sorry for any stupid errors its only my 3rd week using any unix product, I have been a windows admin my whole life)
Issue:
I need to ssh into the PC's update the /etc/shadow file but only change the root user (not all systems have the same users and I don't want to remove any of those users in the process) I have gotten as far as being able to extract the current user in line 1 through ssh, then check if that user is indeed the root user but I am stuck on then updating the /etc/shadow file on the new machine as my boss has asked that the following standards happen.
I can't have any real user interaction in the script, so no manually typing the new passwd.
I am not allowed to have the new passwd displayed anywhere in clear text (inside the script or in another file)
Ok hopefully that's enough info onto the code.
root=user
unknown='unknown.txt'
filelines=`cat $unknown`
prod='new-shadow'
ohf='option-one-holding-file'
pel=prod-errorlog
for line in $filelines ; do
echo "Attempting to fix $line please wait"
ssh -oBatchMode=yes -l $user $line "awk '{if (NR==1) print \$0}' /etc/shadow" >> $ohf
if grep -q "root:" $ohf ; then
echo "root user located updating to produtcion password"
# ** This is the line that doesn't work **
ssh -oBatchMode=yes -l $user $line "sed -i '1s/.*/$prod/' /etc/shadow"
else
echo "unable to find root user this will require a manual fix this server will be listed in
the prod-errorlog file"
echo "$line" >> $pel
fi
done
The line in bold the sed line doesn't work I know why it doesn't work but I have no idea how to fix it at all, thank you to anyone who takes the time to look at this, I know the codes a bit of a mess, please forgive me.
To replace only the first line:
"echo '$prod' > /etc/shadow.new; tail -n +1 /etc/shadow >> /etc/shadow.new; mv -f /etc/shadow.new /etc/shadow"
Sorry for my previous wrong argument wrong: The '$prod' part in your script is correct, and is expanded OK. Yet $prod contains many reserved characters for regular expressions. Now this new version just create a new file (replacing the first line) and then move/overwrite on to the target one.

OSX Bash Shell Script Does Not Run

I'm having a pretty basic shell script that's supposed to run at user login. To achieve this, I followed the guide for Automator from the first answer in this topic: Running script upon login mac
But somehow nothing happens. I also tried to create an application using the script editor with do shell script /blabla/git_credentials.sh which responded with a permission denied.
I don't see whats wrong here.
Oh, here's the script:
echo ""
echo "Setup Git Credentials"
echo "*********************"
echo "Please enter your first name: "
read fname
echo "Please enter your last name: "
read lname
echo "Please enter your mail address: "
read email
git config --global --remove-section user
git config --global user.name "$fname $lname"
git config --global user.email $email
echo "Credentials set."
Edit: I just found out that the script is being run at login, but it neither opens up a terminal nor waits for my user inputs, I have just an empty Git config after every startup. I 'achieved' this using the script editor with do shell script "$HOME/git_credentials.sh" and saving it as an application, then putting it into the login items.
The problem is that your Automator's shell script isn't connected to STDIN (i.e. your keyboard). It may run the shell script, but there's no way to pass it input since there's no terminal.
What you need to do is run the Automator action: Ask for Text to get your input.
What I found I had to do was Ask for Text, and then Set the Value of the Variable. I do this for each variable I want as input.
Once I get all of the variables I want, I then run Get the Value of the Variable for each of the variables. This puts the variables into $* for the shell script to pull up.
Now, you can execute the Automator action Run Shell Script with Pass Input as arguments. You can refer to them as $1, $2, etc.
I suggest to try this with a simple script and see if it then works. The problem is that the whole thing may execute in a sub-shell, so once the automator action ends, you lose the values of the variables you've set. I simply don't have enough experience with Automator to know exactly how it works.
I suspect you script is not currently executable.
Try fixing this by running:
chmod +x /blabla/git_credentials.sh
or
chmod 755 /blabla/git_credentials.sh
Or you are missing #!/bin/bash at the top of your script? Or is this just a part of it?

Run a Bash Script automatically upon login

I wrote a script that sends the date and username of the person who logs in to a log file to keep a record of who has logged in. I am wondering how can you set this script to execute automatically when a user logs in rather than have to manually run it in the terminal. NOTE: the USERNAME is the current user that is logged in.
my code:
#!/bin/bash
printf "$(date) $HOSTNAME booted!\n" >> /home/USERNAME/boot.log
A more elegant way to solve this problem is to read from log files that are already being written and cannot be changed by the user. No one could say it better than Bjørne Malmanger's in his answer:
I wouldn't trust the user to GIVE you the information. As root you
TAKE it ;-)
A nice way to do this is the last command, which is great because it neatly displays all logins: Graphical, console and SSH.
last
A less elegant but still secure way is to do a grep on /var/log/auth.log. On my Gnome/Ubuntu system I can use this to track graphical logins:
grep "session opened for user USERNAME"
The right pattern for your machine needs to be found for each login type: graphical, console and SSH. This is cumbersome, but you might need to do it if you need information that goes further back than last reaches.
To directly answer your question:
You can modify the script like this to get the username
#!bin/bash
printf "$(date) $HOSTNAME booted!\n" >> /home/$(whoami)/boot.log
And add this line to /etc/profile
. /path/to/script.sh
This is not secure though because the user will be able to edit his own log
Why don't you use the last command?
I wouldn't trust the user to GIVE you the information. As root you TAKE it ;-)
Put it in ~/.bash_profile. It will be run each time they log in.
More information is available at the women's rights page (i.e. man bash).

Resources