How do I get this to display the shell? - linux

To get this code to run properly, I created a txt file named new_user.txt with the following format (supposed to follow /etc/passwd)
doejjan:x:Doe, Jane Joe+111222:home/STUDENTS/teststu:/bin/bash
smidjoh:x:Smith, John Jay+222333:home/STUDENTS/teststu:/bin/bash
I want to try to display the command that was created to show every record on the screen, below is what I have so far:
#!/bin/bash
while read -r line || [[ -n "$line" ]]; do
username=$(echo "$line" | cut -d: -f1)
GECOS=$(echo "$line" | cut -d: -f5)
homedir=$(echo "$line" | cut -d: -f6)
echo "adduser -g '$GECOS' -d '$homedir' -s /bin/bash '$username'"
done < "$new_user.txt"
I'm getting the error in line 7 that says the following:
.txt:No such file or directory
Can you help me try to fix the error message? Thank you in advance.

From the error message, you can understand that the variable new_user must be empty. Indeed you never assign a value to this variable.
From your description, it follows that $new_user should expand to the value new_user. Say your script is called my_script. If you run it as
new_user=new_user my_script
the error will be gone. If the script is run most of the time on the file new_user.txt, you can - in your script - provide a default value for this variable:
: ${new_user:=new_user}
If you then run it as
my_script
it will pick up new_user.txt, but if you run it by
new_user=old_user my_script
it will run on old_user.txt.
BTW, I personally would prefer passing the file name to the script either via stdin or on the command line, but you have choosen to use a variable for this task, and you can do this of course, if you prefer.

Related

getting first column of a matching line in bash

I am getting an output from a shell command, and want to incorporate the first column of a matching line into a second command. Here is what I have, and it works:
kubectl get pods -n system | while read string; do
if [[ "$string" == my-pod-* && "$string" == *Running* ]]; then
# echo $string
read -ra ADDR <<< "$string"
echo
echo "--- Reading logs for ${ADDR[0]} ---"
# desired output: kubectl -n system logs my-pod-123 --tail=5 -f
kubectl -n system logs ${ADDR[0]} --tail=5 -f
fi
done
the output from first command would look something like this:
name status namespace running
my-pod-123 Running system 4h31m #<<I want this one
another-pod-5 Running system 5h15m
my-pod-023 Terminating system 8h05m
given that the output will contain only one match, is there a shorter way to do this without looping like this? Thanks in advance for helping me improve my Bash skills as this seems very clumsy.
You may use awk like this:
name=$(kubectl get pods -n system | awk '/^my-pod.*Running/{print $1}')
[[ -n $name ]] && kubectl -n system logs "$name" --tail=5 -f
awk command will match pattern my-pod.*Running at the start of a line and if it is found then it will print first column. We store that in variable name.
If $name is not empty then we call kubectl -n system logs using that value.
How about grep?
wanted=$(kubectl get pods -n system | grep 'my-pod-.*Running')
Can do error checking at the same time:
if ! wanted=$(kubectl get pods -n system | grep 'my-pod-.*Running'); then
echo "Error: no running my-pods" >&2
fi

BASH save stdout to new file upon execution

please bear with me if my terminology or syntax is less than stellar (still learning). I currently have a simple bash script that checks the arguments of the command and outputs files names with matching text. This part of my script works correctly via a grep command and piped to xargs for proper formatting.
When running the script, I run through a simple loop to check if the value is null and then move to running my variable/search if not.
My question is: Is it possible to have this script output via stdout AND also save a new file each time it is run with the user input and date/time? (but not overwrite) EX: report-bob-0729161500.rpt
I saw same other suggestions to use tee with the command, but I was trying to get it to work within the script. Similarly, another suggestion stated to utilize exec > >(tee -i logfile.txt), but I am unsure how to properly format this to include the date/time and $1 input into new files each time the script is executed.
Any help or suggested resources?
Thank you.
SEARCH=`[search_variable]`
if [ -z "$SEARCH" ]
then
echo "$1 not found."
else
echo -e "REPORT LISTING\n\n"
echo "$SEARCH"
fi
EDIT: I did try simply piping the echo statements to the tee command, which does work. However, I am still curious if anyone has other suggestions to accomplish this same task via alternative methods. Thank you.
With echo statements piped to tee:
SEARCH=`[search_variable]`
DATE=`date +"%m%d%y%k%M"`
if [ -z "$SEARCH" ]
then
echo "$1 not found."
else
echo -e "REPORT LISTING\n\n" | tee tps-list-$1-$DATE.rpt
echo "$SEARCH" | tee tps-list-$1-$DATE.rpt
fi
If you want to do it within the script, why then not just write to
both standard output and the file (using append where appropriate?).
Maybe a bit more writing, but it gives complete control.
Leon

Calling a shell script that is stored in another shell script variabl

I searched SO but could not find any relevant post with this specific problem. I would like to know how to call a shell script which is stored in a variable of another shell script.
In the below script I am trying to read service name & corresponding shellscript, check if the service is running, if not, start the service using the shell script associated with that service name. tried multiple options shared in various forums(like 'eval' etc) with no luck. please help to provide your suggestions on this.
checker.sh
#!/bin/sh
while read service
do
servicename=`echo $service | cut -d: -f1`
servicestartcommand=`echo $service | rev | cut -d: -f1 | rev`
if (( $(ps -ef | grep -v grep | grep $servicename | wc -l) > 0 ))
then
echo "$servicename Running"
else
echo "!!$servicename!! Not Running, calling $servicestartcommand"
eval "$servicestartcommand"
fi
done < names.txt
Names.txt
WebSphere:\opt\software\WebSphere\startServer.sh
WebLogic:\opt\software\WebLogic\startWeblogic.sh
Your script can be refactored into this:
#!/bin/bash
while IFS=: read -r servicename servicestartcommand; do
if ps cax | grep -q "$servicename"; then
echo "$servicename Running"
else
echo "!!$servicename!! Not Running, calling $servicestartcommand"
$servicestartcommand
fi
done < names.txt
No need to use wc -l after grep's output as you can use grep -q
No need to use read full line and then use cut, rev etc later. You can use IFS=: and read the line into 2 separate variables
No need to use eval in the end
It is much simpler than you expect. Instead of:
eval "$servicestartcommand"
eval should only be used in extreme circumstances. All you need is
$servicestartcommand
Note: no quotes.
As an example, try this on the command-line:
cmd='ls -l'
$cmd
That should work. But:
"$cmd"
will fail. It will look for a program with a space in its name called 'ls -l'.
May be I don't get the idea, but why not use system variables?
export FOO=bar
echo $FOO
bar

Why can't this script execute the other script

This script looks for all users that have the string RECHERCHE inside them. I tried running it in sudo and it worked, but then stopped at line 8 (permission denied). Even when removing the sudo from the script, this issue still happens.
#!/bin/bash
#challenge : user search and permission rewriting
echo -n "Enter string to search : "
read RECHERCHE
echo $(cat /etc/passwd | grep "/home" | cut -d: -f5 | grep -i "$RECHERCHE" | sed s/,//g)
echo "Changing permissions"
export RECHERCHE
sudo ./challenge2 $(/etc/passwd) &
The second script then changes permissions of each file belonging to each user that RECHERCHE found, in the background. If you could help me figure out what this isn't doing right, it would be of great service. I
#!/bin/bash
while read line
do
if [-z "$(grep "/home" | cut -d: -f5 | grep -i "$RECHERCHE")" ]
then
user=$(cut -f: -f1)
file=$(find / -user $(user))
if [$(stat -c %a file) >= 700]
then
chmod 700 file 2>> /home/$(user)/challenge.log
fi
if [$(stat -c %a file) < 600]
then
chmod 600 file 2>> /home/$(user)/challenge.log
fi
umask 177 2>> /home/$(user)/challenge.log
fi
done
I have to idea what I'm doing.
the $(...) syntax means command substitution, that is: it will be replaced by the output of the command within the paranthesis.
since /etc/passwd is no command but just a text-file, you cannot execute it.
so if you want to pass the contents of /etc/passwd to your script, you would just call it:
./challenge2 < /etc/passwd
or, if you need special permissions to read the file, something like
sudo cat /etc/passwd | ./challenge2
also in your challenge2 script, you are using $(user) which is wrong as you really only want to expand the user variable: use curly braces for this, like ${user}
/etc/passwd?
not what you were asking, but you probably should not read /etc/passwd directly anyhow.
if you want to get a list of users, use the following command:
$ getent passwd
this will probably give you more users than those stored in /etc/passwd, as your system might use other PAM backends (ldap,...)

Add user account from file script error [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Linux Script Extract Information From Excel To Create Users
Need to create users from excel spread sheet, getting a few errors in my script on lines 8 and 13
Line 8 Unexpected EOF while looking for matching `''
Line 13 Syntax error unexpected end of file
#!bin/bash
echo $(pwd)/employeesdata.xls
Path=$($pwd)/employeesdata.xls
read Path
if [ -e $Path ];
then
Username= [ grep $(Username) $Path | cut -f1 -d `]'
Password= [ grep $(Password) $Path | cut -f2 -d `]'
useradd -- b $Username
echo $Password | /usr/bin/passwd --stdin $Username
fi
exit
Excel file has this and other information
Name (field1) EmployeeID (field2) Phone Address
Joe Blow 22500033 156-454-3322 101 main
I think you'd have to refactor a few things:
#!bin/bash
echo $(pwd)/employeesdata.xls
Path="$(pwd)/employeesdata.xls"
read Path
if [ -e "$Path" ]; then
Username=$(grep "$Username" "$Path" | cut -f1 -d ' ')
Password=$(grep "$Password" "$Path" | cut -f2 -d ' ')
useradd -- b $Username
echo "$Password" | /usr/bin/passwd --stdin "$Username"
fi
exit
A few notes:
Quote the value you are assigning to a variable (sometimes this is not necessary, but for starting out it helps to avoid some problems)
Quote the usage of a variable, unless you know what you're doing. Without quoting it explicitly, the variable can generate various parameters to commands/functions.
$(cmd) executes the command cmd and replaces its occurrence with the output of the command.
$var or ${var} replaces itself with the contents of variable named var
"quoting $a", supposing the variable a contains string as its contents, generates the string quoting string.
'quoting $a', independent of the variable a, generates the string quoting $a.
As confusing as it can be for newcomers, [ is actually an "alias" for the test command, which can be used to compare strings, integers, and do some basic tests like checking the permissions or the existence of a file. ] is actually just a syntax requirement just to inform the command that its parameters have ended (when called .
I assumed your delimiter is a space, but I could be wrong.
Hope this helps a little =)

Resources