bash input/ouput to a log file - linux

I have a bash script with below statement. I need to output both the question "Are you happy? and the answer "yes" or "no" to a log file. I'm able to get the answer to log file with "echo "$yn" >>log1.log 2>&1" but not the question (read command)
while true; do
read -p "Are you happy? " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
echo "$yn" >>log1.log 2>&1
What I have tried:
read -p "Are you okay?" yn > log.log 2>&1
This will indeed work, however when I run my scrip the question is not displayed.
The only way I found is to echo "Are you happy? $yn" >>log1.log 2>&1
The problem with this is that I have several prompts with long statements, I like to keep my scripts nice and short

The redirect only applies to the echo. You need to add a similar redirect afther the done. (This will also redirect the error message which you echo from within case, which incidentally should go to standard error):
while true; do
read -p "Are you happy? " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no." >&2;;
esac
done >>log1.log 2>&1
echo "$yn" >>log1.log
or put the entire sequence of commands inside parenthes or braces.
{ while true; do
read -p "Are you happy? " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no." >&2;;
esac
done
echo "$yn"; } >>log1.log 2>&1
Like you discovered, and like the term should reveal, a redirection causes the output to go to another place (so a file instead of your terminal, in this case). If you want it displayed on the terminal as well, tee does that, but it's probably not suitable for interactive scripts (because you can't include standard input in the output).
tripleee$ cat >nst
#!/bin/bash
while true; do
read -p "Are you happy? " yn
case $yn in
[Yy]*) break;;
[Nn]*) exit;;
*) echo "Please answer yes or no." >&2;;
esac
done
echo "$yn"
^D
tripleee$ chmod +x ./nst
tripleee$ ./nst 2>&1 | tee log1.log
Are you happy? forget it
Please answer yes or no.
Are you happy? no
tripleee$ cat log1.log
Are you happy? Please answer yes or no.
Are you happy? tripleee$
Perhaps you are actually looking for the script command?
tripleee$ script typescript ./nst
Script started, output file is typescript
Are you happy? forget it
Please answer yes or no.
Are you happy? yes ma'am
yes ma'am
Script done, output file is typescript
tripleee$ nl -ba typescript
1 Script started on Thu Oct 26 20:34:04 2017
2 command: ./nst
3 Are you happy? forget it
4 Please answer yes or no.
5 Are you happy? yes ma'am
6 yes ma'am
7
8 Script done on Thu Oct 26 20:34:11 2017
Note that the typescript file will contain any edits done by the user, i.e. typos and their correction will be included, with the various display codes used by the terminal to execute the edits.

Related

Exiting "while true; do" loop in shell script prompt

My current project on Linux is to make a script that has three options: yes, no and false input. The last one would cause the script to loop back to the question, but with my current method, even the "yes" option loops back to the original statement. I'm incredibly confused as to how I can fix this. Here's the part of the script I mean:
while true; do read -p "Do you want to run the script now? (Y/N) " yn
case $yn in
[Yy]* ) echo "Permission granted, running commands...";;
[Nn]* ) echo "Operation aborted, exiting..." && exit;;
* ) echo "Incorrect input detected, exiting...";;
esac
done
... more code
How can I make the first command execute the rest of the script, while keeping the function of this loop for the last command at hand?
It seems you want to break out of the loop and execute the "more code" that comes after. That's what a break command is for.
while true; do read -p "Do you want to run the script now? (Y/N) " yn
case $yn in
[Yy]* ) echo "Permission granted, running commands..." && break;;
[Nn]* ) echo "Operation aborted, exiting..." && exit;;
* ) echo "Incorrect input detected, exiting...";;
esac
done

Is there a way that you can use the "if" branch to check whether a USB stick is connected?

Is there a way like that you can use the "if" branch to check whether a USB-Stick is connected? And if the stick is not connected, a message should then be issued.
Something like:
if [-e /sdb1]
then
cp /home/backup/* /sdb1
rm -r /home/backup/*
echo "your files are successfully transferred."
else
echo "please be sure, if your USB-Stick is connected"
fi
No, the mount point exists whether or not a USB device is connected.
Something like this should suffice:
if [[ $(df | grep "/sdb1") && -d /sdb1 && -w /sdb1 ]]
That is if, of course, you have actually created the directory /sdb1/.
Use the findmnt utility (installed by default on RH and Ubuntu, at least)
findmnt /backup
echo $?
1
Return of 1 means not mounted.
Here is some sample code using it with an if statment
findmnt /backup >/dev/null
if [ $? = 0 ]; then
echo "It's mounted all right"
else
r=$(( RANDOM % 4 ))
echo "USB is not mounted."
case $r in
0) echo "Check the couch cushions."
;;
1) echo "I think I saw it in the kitchen."
;;
2) echo "Sign up for Prime and get free shipping!"
;;
3) echo "The dog ate it."
;;
esac
fi

bash script to add and remove users

I am a beginner in bash scripting and I have created a bash script to add users and remove users on Linux. But since I am facing some issues with the script not really major issues but would be helpful if anyone could point me how to improve the script and the worst practice I am doing the script would be helpful
however the problem I have noticed is that the script takes -a to add a user -d to remove user and -h to get help the -a flag as 2 optional arguments -p for password and -s for shell so the command would be
./useradd.sh -a user -p password -s shell
this works as expected and the user is added to the system but the problem I am facing is that if I do not enter -a flag and specify the -s and -p flag the script is just exited I want to show a clear idea to the user why it exited and there is so many such errors I am assuming but I have not tested it out so much any help would be appreciated, so here is my script
#!/bin/bash
## checking if the user is privileged or not
if [[ $EUID != 0 ]]
then
echo "Script has to be ran as root or sudo"
echo "Aborting"
exit 101
fi
## creating help functions
function usage() {
echo "usage: ${0} -a <user> -p <password> -s <shell> | ${0} -d <user> | ${0} -h"
}
function help() {
echo "$0 - Script to add of remove users"
echo "-a - Add a new user"
echo " -p - Set password while creating user if not mentioned will not set any password by default"
echo " -s - Set a shell for the user default is /bin/bash if none specified"
echo "-a - Remove a user"
echo "-h - Print this help text"
}
if [[ "$#" -lt "1" ]]; then
echo "Argument has to be provided see $0 -h"
fi
shell=/bin/bash
password=$(openssl rand -base64 32)
while getopts :a:d:h opt; do
case $opt in
a) user=$OPTARG
while getopts :p:s: test
do
case $test in
p) password=$OPTARG;;
s) shell=$OPTARG;;
/?) echo "The provided flag is not identified see $0 -h"
exit;;
:) echo "$OPTARG requires arguments see $0 -h"
exit;;
esac
done
if [[ "$1" != "-a" ]]
then
echo "You have to specify username using -a flag see $0 -h"
fi
useradd -m $user -s $shell
echo "$user":"$password" | chpasswd
echo "The password for the $user is $password";;
d) userdel -f $OPTARG
if [[ $? == 0 ]]
then
echo "user has been removed"
else
echo "There was some error removing the user"
fi;;
h) help
exit;;
/?) echo "$OPTARG option not valid";;
:) echo "$OPTARG requires argument";;
esac
done
Please show your code! I usually process args with case ... in likes :
#!/bin/bash
while [[ $# -gt 0 ]]; do
case $1 in
"-a")
echo "-a is $2"
shift 2;;
"-d")
echo "-d is $2"
shift 2;;
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

Validate input from bash

I need to make a bash script that takes user input and does some validation.
The input is small. I just need to get a user choice "yes" or "no" and a file path and make sure the input is indeed a filepath and that he entered yes or no.
How can I validate the user input?
from your bash prompt type
help read
example:
step 1.
pete#ruthie ~ $ read -p "Yes or No :" ANSWER
Yes or No :Yes
pete#ruthie ~ $ echo $ANSWER
Yes
step 2.
case $ANSWER in
Y* | y* ) echo "ANSWER is yes" ;;
N* | n*) echo ANSWER is no;;
*) echo "Unclear Response" ;;
esac
ANSWER is yes
Or all on one line:
case $ANSWER in Y* | y* ) echo "ANSWER is yes" ;; N* | n*) echo ANSWER is no;; *) echo "Unclear Response" ;; esac
ANSWER is yes
So something vaguely like::
read -p "Enter File Name :" FILE_TO_CHECK
if [ ! -e "$FILE_TO_CHECK" ]; then
echo -e "There is no file called $FILE_TO_CHECK \n please check spelling"
else
echo "Congratulations found $FILE_TO_CHECK. "
ls -lah $FILE_TO_CHECK
read -p "Process $FILE_TO_CHECK ? Y or N : PROCEED
case $PROCEED in
Y* | y*)
##call function or system command to do something with this data
foo $FILE_TO_CHECK
;;
* )
echo -e "Note $USER\n No action taken by $0 on $FILE_TO_CHECK"
;;
esac
fi
The test command is your friend. You really need to learn its ways ASAP.
help [
and
help test
The "help bashthing" command is a great quick reminder.
see also: the Advanced Bash Scripting Guide (ABS)
http://tldp.org/LDP/abs/html/
FWIW:
This is a very simple example and wont accommodate much in the way of unexpected user input.
I would probably call functions for each step of this as then I could conditionally represent the user with another chance.
The case tests nested like this is plain ugly :) === hard to get neat and read later
There are other ways to achieve all this try zenity for a GTK style GUI.
The A.B.S is excellent but dont try to eat it all at once !

Resources