bash script - how to create and store user activity - bash

i am writing a script so far i created a log-in system but want to create a .db file to store user activity like to store what time they logged in, logged out and when did they order a meal.
this is the small script i wrote
#!/bin/bash
function login_system(){
printf "%s\n" "write your username below"
read user
grep ^"$user:" /etc/pass > /dev/null
if [ $? -eq 0 ]
then
printf "%s" "confirmed"
sleep 2
menu_system
else
printf "%s" "denied"
sleep 2
login_system
fi
}
function menu_system(){
printf "%s\n" "press one to order a breakfast and 2 to exit"
read order
if [ $order -eq 1 ]
then
. breakfast
printf "%s\n" "returing back to menu system"
sleep 3
menu_system
else
exit
fi
}
login_system
exit 0
i just dont know how to implement user activity script, i tried researching but couldn't find anything. any guide or help would be greatly appreciated.

This looks like a homework problem, so I'll answer with a good resource: How to redirect script output to a file.
If this is a question for an actual production system, then somebody is crazy. You do not implement systems like this in Bash.

here is the answer i manged to work out using printf
printf $user >> useractivity.db
printf " " >> useractivity.db
echo $(date) >> useractivity.db
use >> just to write on top of it
use > to over write it

Related

Bash: using netcat to call a function "remotelly", even possible?

(I have been testing (trying) like a thousand posts like chats, web servers, server-clients for netcat, no luck so far, therefore thinking if is it possible at all)
Lets say I have a silly bash function that all that does is to reply you saying you hello and how long is your name, and a script, on interactive console input so users can fell good (./myScript.sh interactiveBash):
#!/bin/bash
responseTo(){
local output=$1
local input=$2
plentyOfThings="Hello $input, you name is ${#input} characters long, and youre gona have a great day"
##may take a while, on tests, up to 3-5 seconds
eval $output="'$plentyOfThings'"
}
if [ "${1}" == "interactiveBash" ]
then
echo -n "What's you name? "
while read; do
response=""
responseTo response ${REPLY}
echo "··························· ${response}"
echo -ne "\nWhat's you name? "
done
fi
Cool, I run in a terminal, user can put his name, and terminal say hello and wish them a great day
now, becouse how that pretty complex function (responseTo) count the lenght of the name is pretty secret, need to be on a remote computer
so I tought to extend my scritp with (./myScript.sh onlineNetcatServer):
if [ "${1}" == "onlineNetcatServer" ]
then
my_port=8080
echo "Listening at ${my_ip}, and aying hello"
while true; do
nc -kl ${my_port} -w 0 \
0< < .... \
1> > .... \
2> .... #errors
....
echo "${_input} was here on IP ${_IP} and I told him ${_resposne}"
done
fi
and then give user the following script (./myScript.sh 192.168.1.42)
remome_ip=${1}
remote_port=8080
echo -n "What's you name? "
while read; do
response=""
nc -kl ${remome_ip} ${remote_port} -w 0 \
0< < ....${REPLY}.... \
1> > ....${response}.... \
2> .... #errors
....
echo "··························· ${response}"
done
sure, all comands in betwwen dots are missing, and no idea how to continue
(like the server will "serve" multiple clients, the netcat session need to be closed as soon as response is given, and preferiable, keep other waiting until served)
is that even possible with this estructure / usage of NetCat ??

why is a bash read prompt not appearing when a script is run?

I have a bash script that prompts the user for different information based on what they're trying to do. The prompts are usually done with read -p. Usually it works just fine, the user sees what is being asked, enters what they need to enter, and everything does what it needs to do.
See the following (sanitized) snippet of a function in the script:
#!/bin/bash
function_name() {
if [ "$this_value" == "default" ];then
echo "Value set to default."
read -p "Enter desired value here: " desired_value
desired_value=${desired_value^^}
if [ "${#desired_value}" != 3 ] ;then
echo "$desired_value is an invalid entry."
exit 1
fi
if [ "$desired_value" != "$(some command that returns something to compare against)" ];then
echo "$desired_value is an invalid entry."
exit 1
fi
read -p "You entered $desired_value. Is this correct? [y/N] " reply
reply=${reply,,}
case "$reply" in
y|yes)
$some command that does what I want it to do
;;
*)
echo "User did not enter yes"
exit 1
;;
esac
fi
}
Usually the Enter desired value here and is this correct? lines appear just fine. But in a few instances I've seen, for some reason the read prompt is just blank. A user will see the following:
./script.bash
##unrelated script stuff
##unrelated script stuff
Value set to default.
user_entered_value_here
User did not enter yes. Exiting.
This is a real example that just happened that finally made me come here to ask what is going on (and I modified appropriately to make it an SO post).
What's happening is these two blank lines appear instead of the read -p text. For the first one, the user entered user_entered_value_here because they already know what is supposed to be entered there even without the read prompt. The second one, the Y/N prompt, they don't know, so they see it apparently hanging, and hit Enter instead of y, causing it to trigger the * case option.
I don't understand why the read -p text is not appearing, and especially why it's appearing for most users but not all users. I suspect there's some kind of environmental setting that causes this, but for the life of me I can't figure out what. This is being run only on RHEL 6.2, under bash 4.1.2.
I looked at the man of bash to catch some kind of detail about the read built-in. It is specified that -p option displays the "prompt on standard error, without a trailing newline, before attempting to read any input. The prompt is displayed only if input is coming from a terminal".
Let's consider the simple script input.sh:
#!/bin/bash
read -p "Prompt : " value
echo The user entered: "$value"
Example of execution:
$ ./input.sh
Prompt : foo
The user entered: foo
If stderr is redirected:
$ ./input.sh 2>/dev/null
foo
The user entered: foo
If the input is a pipe
$ echo foo | ./input.sh
The user entered: foo
If the input is a heredoc
$ ./input.sh <<EOF
> foo
> EOF
The user entered: foo
Rewrote your script with shell agnostic grammar and fixed some errors like comparing the string length with a string comparator != = rather than a numerical comparator -ne -eq:
#!/usr/bin/env sh
this_value=default
toupper() {
echo "$1" | tr '[:lower:]' '[:upper:]'
}
function_name() {
if [ "$this_value" = "default" ]; then
echo "Value set to default."
printf "Enter desired value here: "
read -r desired_value
desired_value=$(toupper "$desired_value")
if [ "${#desired_value}" -ne 3 ]; then
printf '%s is an invalid entry.\n' "$desired_value"
exit 1
fi
if [ "$desired_value" != "$(
echo ABC
: some command that returns something to compare against
)" ]; then
echo "$desired_value is an invalid entry."
exit 1
fi
printf 'You entered %s. Is this correct? [y/N] ' "$desired_value"
read -r reply
reply=$(toupper "$reply")
case $reply in
'y' | 'yes')
: "Some command that does what I want it to do"
;;
*)
echo "User did not enter yes"
exit 1
;;
esac
fi
}
function_name

Need way to approve bash cmd exec before running w/o affecting echo return

Currently trying to write bash that will do the following.
check if curl is installed
print out "which curl" before running it so that the user is able to opt in/out of running something they consider unsafe.
Use case is when you download a big script from github and you want to have more control over what it is doing. Also to be more aware of how it works.
I am not sure how to include this opt in/out code without messing up the "return" echo. Maybe the answer is to use something different that the read -n 1 -s -r -p code. I like that solution because it allows hitting any key to continue.
To be clear. If I check for YES/NO later on, it is messed up because it will contain the character used to continue by pressing any key. In my output example the space bar was hit to continue
#! /bin/bash
# Returns YES if installed otherwise return NO
check_curl_installed() {
echo >&2 "Before running, the command will be printed below."
echo >&2 "Press any key to approve running it"
read -n 1 -s -r -p "which curl"
echo ""
if which curl > /dev/null; then
echo "YES"
else
echo "NO"
fi
}
main() {
RESULT=$(check_curl_installed)
echo $RESULT
echo x${RESULT}x
}
main "$#"
exit 0
This is the output
user#computer:tmp$ ./check_curl_installed.sh
Before running, the command it will be printed below.
Press any key to approve running it
which curlYES
x YESx
Instead of using the output of the function, use its exit status.
check_curl_installed() {
echo >&2 "Before running, the command will be printed below."
echo >&2 "Press any key to approve running it"
read -n 1 -s -r -p "which curl"
echo ""
if which curl > /dev/null; then
return 0
else
return 1
fi
}
if check_curl_installed
then
# do something
else
# do something else
fi
how about this modified version to get only the Y key to answer...
#! /bin/bash
# Returns YES if installed otherwise return NO
check_curl_installed() {
echo >&2 "Before running, the command will be printed below."
echo >&2 "Press Y key to approve running it"
read -n 1 -r -s -p "Which curl?"
if [[ $REPLY =~ ^[Yy]$ ]]; then
if which curl > /dev/null ; then
printf "\nYES It is installed\n"
else
printf "\nNO It is not installed\n"
fi
else
printf "\nExiting - not checking\n"
fi
}
main() {
check_curl_installed
}
main "$#"
exit 0
Your echo result is, i think just pulling the first line of the check_curl_installed function...
Maybe if result was set to an array?
my testing around has shown that it's forgetting variables in the function at the higher main function. I even tried exporting to get the main function to work, but to no avail. I'm not super strong in bash, so i apologize on that.
Also might work better to put the echos inside each function, instead of shoving them into a variable...
Most, if not all, languages, only return one value from a function. Maybe this is why your output don't do as you want? a quick search brought this up https://unix.stackexchange.com/questions/408543/how-can-a-bash-function-return-multiple-values

Loop to ask user via keyboard for filename to be used or q to exit in bash

I'm having issues with a script I'm writing in bash with regards to backing up or restoring. What I'm trying to do is check for parameters and then if none are presented, loop until a name is provided or they quit. I can check for parameters and loop to quit but the problem I am having is getting the user input and then using that for the backup file name. Here's my script so far, can someone advise on how to loop for filename/q and how to get said filename input to work with the rest of the script?
#!/bin/bash
# Purpose - Backup world directory
# Author - Angus
# Version - 1.0
FILENAME=$1.tar.gz
SRCDIR=World
DESDIR=backupfolder
if [ $# -eq 0 ]
then
echo "No filename detected. To use this utility a filename is
required. Usage:tarscript filename"
else
echo "The filename to be used will be $filename"
fi
while [ $# -eq 0 ]
do
echo "Please provide a filename or press q to exit."
read response
if [ $response == 'q' ]
then
exit
else [ $response == '$FILENAME' ]
echo -n 'Would you like to backup or restore? (B/R)'
read response
if [ $response == 'B' ]
then
tar cvpzf $DESDIR/$FILENAME $SRCDIR
echo 'Backup completed'
exit
fi
fi
done
I finally managed to get it working in the end. I realised what my mistakes were thanks to Jens and changed things enough that it now responds to input and supplied parameters. Of course the code is nearly twice as big now with all my changes but hey ho.

Add debug mode to bash script

first of all, sorry for my bad english.
I want to enbale debug mode, with date. I was thinkging in a variable that use one type of redirection, or another, like this:
#!/bin/bash
DEBUG_MODE=1
if [ $CHAMAC_DEBUG = 0 ]; then
output=/dev/null
elif [ $CHAMAC_DEBUG = 1 ]; then
output=>( while read line; do echo "$(date): ${line}"; done >> ~/output.log )
fi
echo "hi, im a echo" &> $output
But it dont work for me.... how can do it¿?¿?
I'm not quite sure what you mean by "debug mode", but if you want to print additional output only when a particular variable is defined you could do something like this:
#!/bin/bash
function print_debug {
[ $DEBUG_MODE -eq 1 ] && echo "$(date) $1"
}
DEBUG_MODE=0
print_debug "Test 1"
DEBUG_MODE=1
print_debug "Test 2"
Output:
$ ./test.sh
Test 2
You could also separate debug output from regular output by echoing debug messages to a different file descriptor:
function print_debug {
[ $DEBUG_MODE -eq 1 ] && echo "$1" 1>&3
}
That way you can redirect STDOUT, STDERR and debug output to different files if needed.
Your question is hard to understand, but perhaps you are looking for something like this?
debug () {
date +"[%C] $*" >&2
}
if ... whatever ...; then
dbg=debug
else
dbg=:
fi
$dbg "script started"
:
Wherever you want to output a diagnostic, use $dbg instead of echo.
(You have to double any literal percent sign in your debug prints, or make the function slightly more complex.)
You can use an alternate file descriptor for this (along with a few other fixes):
if [[ "${CHAMAC_DEBUG}" == "1" ]]
then
exec 3>> ~/output.log
else
exec 3>> /dev/null
fi
{ echo "$(date) : hi, im a echo"; } >&3
The process substitution syntax wants to see the name of a program, not a bash internal command like while. You could maybe get it to work using something like >(bash -c 'some stuff here'), but the above is simpler, I think. The only downside is you have to do your own date-stamping... If that's a problem, you could look into submitting your debug messages to syslog (via logger) and configure that to dump those specific messages in a file of their own...

Resources