execute multiple commands assigned to a single variable - bash - linux

I would like to ask the user to enter a command that will be executed, but I don't understand why I can't assign two commands to the same variable.
Here is the code:
user#localhost:~# read -ep "command: " cmd ; "$cmd"
and the result:
command: id ; date
-bash: id ; date : command not found
but if I type a single command, it works.
Thanks for your help

Related

Pass in bash terminal variables to a bash script

If I am in a Linux terminal and I start setting variables such as export AGE=45.
Then I have a script to read user data from terminal variables and process it, is this possible to do?
IE:
user#linux$ export AGE=45
user#linux$ ./age.sh
#script asks for input
read -p "what is your age?" scriptAGE
#user inputs variable set in terminal
$AGE
#echo output
echo "your age is: " $scriptAGE"
#should say your age is: 45
There is no such thing as a terminal variable. read just assigns a string to your variable scriptAGE.
If this string contains some $NAME you want to expand, you could apply eval to it, but this is of course extremely dangerous because of possible code injection.
A safer way to do this is using envsubst, but this requires that the variables to be substituted must be environment variables. In your case, AGE is in the environment, so this condition is met.
In your case, you would have to do therefore a
envsubst <<<"$scriptAGE"
which would print on stdout the content of scriptAGE with all environment variables in it substituted.
Variables are not expanded in input, only in the script itself.
You could use eval to force it to process the variable value as shell syntax.
eval "echo 'your age is:' $scriptAGE"
But this will also process other shell syntax. If they enter $AGE; rm * it will say their age is 45 and then delete all their files.
you could just do
age=$1
echo "Your age is $1"
where $1, $2, $3, .., $N are the passed arguments by order
And then run your script
bash script sh Noureldin
For more Info read this:
passing names args

How to compare user input with array and execute command?

I am trying to write a script to login into different systems by providing system name as input and making it variable by read option. However when i try to compare it with defined Array it's throwing me error and stating command not found.
Succeeded in making use input as variable but not able to compare it properly with defined array.
Below is the code i have written.
#!/bin/bash
cluster=("namico1c.mylabserver.com","namico2c.mylabserver.com")
echo "Please enter a Cluster Name to login: "
read clname
for item in ${cluster[#]};do
echo ${item};
if ["${clname}"="${item}"]; then
ssh test#$clname
else
echo "Cluster is not correct"
fi
done
[test#namico3c ~]$ ./test.sh
Please enter a Cluster Name to login:
namico1c.mylabserver.com
namico1c.mylabserver.com,namico2c.mylabserver.com
./test.sh: line 7: [namico1c.mylabserver.com=namico1c.mylabserver.com,namico2c.mylabserver.com]: command not found
Cluster is not correct
alternative:
#!/bin/bash
cluster=("namico1c.mylabserver.com" "namico2c.mylabserver.com")
select clname in "${cluster[#]}"; do
ssh test#$clname
break
done

Shell Script run with TaskSet

I am running the following command on ubuntu:
taskset -c 1 ./forLoop
and its giving me the following error:
./forLoop: 1: Syntax error: Bad for loop variable
What is in forLoop is the following:
for (( i = 0 ; i <= 1000000; i++ ))
do
echo "Welcome $i times"
done
simply ./forLoop does execute by itself but I want to attach the process to a certain affinity. Can I ?
This is likely happening because you're on Ubuntu and the interpreter called dash gets invoked instead of bash.
Trivially, type this to confirm:
dash ./forLoop
You should see the same "for loop" error.
Some of the ways to fix this problem:
Force `bash` to be used: `taskset -c 1 bash ./foo.sh`
Write `#!/bin/bash` as the first line of your script.
Alter the loop code to be dash-compatible, as described in the below link.
Read more here: https://wiki.ubuntu.com/DashAsBinSh/

Bash script to capture input, run commands, and print to file

I am trying to do a homework assignment and it is very confusing. I am not sure if the professor's example is in Perl or bash, since it has no header. Basically, I just need help with the meat of the problem: capturing the input and outputting it. Here is the assignment:
In the session, provide a command prompt that includes the working directory, e.g.,
$./logger/home/it244/it244/hw8$
Accept user’s commands, execute them, and display the output on the screen.
During the session, create a temporary file “PID.cmd” (PID is the process ID) to store the command history in the following format (index: command):
1: ls
2: ls -l
If the script is aborted by CTRL+C (signal 2), output a message “aborted by ctrl+c”.
When you quit the logging session (either by “exit” or CTRL+C),
a. Delete the temporary file
b. Print out the total number of the commands in the session and the numbers of successful/failed commands (according to the exit status).
Here is my code so far (which did not go well, I would not try to run it):
#!/bin/sh
trap 'exit 1' 2
trap 'ctrl-c' 2
echo $(pwd)
while true
do
read -p command
echo "$command:" $command >> PID.cmd
done
Currently when I run this script I get
command read: 10: arg count
What is causing that?
======UPDATE=========
Ok I made some progress not quite working all the way it doesnt like my bashtrap or incremental index
#!/bin/sh
index=0
trap bashtrap INT
bashtrap(){
echo "CTRL+C aborting bash script"
}
echo "starting to log"
while :
do
read -p "command:" inputline
if [ $inputline="exit" ]
then
echo "Aborting with Exit"
break
else
echo "$index: $inputline" > output
$inputline 2>&1 | tee output
(( index++ ))
fi
done
This can be achieved in bash or perl or others.
Some hints to get you started in bash :
question 1 : command prompt /logger/home/it244/it244/hw8
1) make sure of the prompt format in the user .bashrc setup file: see PS1 data for debian-like distros.
2) cd into that directory within you bash script.
question 2 : run the user command
1) get the user input
read -p "command : " input_cmd
2) run the user command to STDOUT
bash -c "$input_cmd"
3) Track the user input command exit code
echo $?
Should exit with "0" if everything worked fine (you can also find exit codes in the command man pages).
3) Track the command PID if the exit code is Ok
echo $$ >> /tmp/pid_Ok
But take care the question is to keep the user command input, not the PID itself as shown here.
4) trap on exit
see man trap as you misunderstood the use of this : you may create a function called on the catched exit or CTRL/C signals.
5) increment the index in your while loop (on the exit code condition)
index=0
while ...
do
...
((index++))
done
I guess you have enough to start your home work.
Since the example posted used sh, I'll use that in my reply. You need to break down each requirement into its specific lines of supporting code. For example, in order to "provide a command prompt that includes the working directory" you need to actually print the current working directory as the prompt string for the read command, not by setting the $PS variable. This leads to a read command that looks like:
read -p "`pwd -P`\$ " _command
(I use leading underscores for private variables - just a matter of style.)
Similarly, the requirement to do several things on either a trap or a normal exit suggests a function should be created which could then either be called by the trap or to exit the loop based on user input. If you wanted to pretty-print the exit message, you might also wrap it in echo commands and it might look like this:
_cleanup() {
rm -f $_LOG
echo
echo $0 ended with $_success successful commands and $_fail unsuccessful commands.
echo
exit 0
}
So after analyzing each of the requirements, you'd need a few counters and a little bit of glue code such as a while loop to wrap them in. The result might look like this:
#/usr/bin/sh
# Define a function to call on exit
_cleanup() {
# Remove the log file as per specification #5a
rm -f $_LOG
# Display success/fail counts as per specification #5b
echo
echo $0 ended with $_success successful commands and $_fail unsuccessful commands.
echo
exit 0
}
# Where are we? Get absolute path of $0
_abs_path=$( cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P )
# Set the log file name based on the path & PID
# Keep this constant so the log file doesn't wander
# around with the user if they enter a cd command
_LOG=${_abs_path}/$$.cmd
# Print ctrl+c msg per specification #4
# Then run the cleanup function
trap "echo aborted by ctrl+c;_cleanup" 2
# Initialize counters
_line=0
_fail=0
_success=0
while true
do
# Count lines to support required logging format per specification #3
((_line++))
# Set prompt per specification #1 and read command
read -p "`pwd -P`\$ " _command
# Echo command to log file as per specification #3
echo "$_line: $_command" >>$_LOG
# Arrange to exit on user input with value 'exit' as per specification #5
if [[ "$_command" == "exit" ]]
then
_cleanup
fi
# Execute whatever command was entered as per specification #2
eval $_command
# Capture the success/fail counts to support specification #5b
_status=$?
if [ $_status -eq 0 ]
then
((_success++))
else
((_fail++))
fi
done

How do I read a value from user input into a variable

In ksh, how do I prompt a user to enter a value, and load that value into a variable within the script?
command line
echo Please enter your name:
within the script
$myName = ?
You want read:
echo Please enter your name:
read name
echo $name
See read(1) for more.
You can do it in a single line, like so:
read -p "Please enter your name:" myName
To use variable in script
echo "The name you inputed is: $myName"
echo $myName
ksh allows you to specify a prompt as part of the read command using this syntax:
read myName?"Please provide your name: "

Resources