How to add one loop arrays value to another loop - bash

I have a script which finds all the Cert. identity on the system then I want to add one more Cert. and delete rest of Cert except which is added recently.
1st loop finds how many identity we have in the system and set array as $var1 $var2 $var3 and no. continues.
Then I add one more.
Now I want to delete 1 loop array values herein for loop. But my $DEL variable is coming as var1 var2, not the actual identity we have set in 1st loop.
#!/bin/bash
DOM=$(/usr/sbin/dsconfigad -show | grep "Active Directory Domain" | awk '{ print $5 }')
MAC=$(/usr/sbin/dsconfigad -show | grep "Computer Account" | awk '{ print $4 }' | tr -d "$")
HOST=$MAC.$DOM
CRT=$(security find-identity -v | grep $HOST | awk '{ print $2}')
set - $CRT; index=0; while [ "$1" ];
do
let index=$index+1;
eval var${index}="$1";
shift;
done
The above loop result is: + set - 02KFKDSF89SFMDFMFS7908934M90DODFSMN78345 K69SKLD04KCM62469933FA60567LLFD730957FA3 489FHDFS93MDF89UY2345905DFSKDDSKFDS9FSEF
echo $var1
echo $var2
The echo $var1 is: 02KFKDSF89SFMDFMFS7908934M90DODFSMN78345
The echo $var2 is: K69SKLD04KCM62469933FA60567LLFD730957FA3
NUMCRT=$index
echo "Number of Certificate is $NUMCRT"
echo "Add of Script part bla bla Start"
echo "ADD one more Cert"
echo "Add of Script part bla bla END"
Now I want to delete array value which I have found in the 1st loop. But $DEL value is coming var1 var2 var3 and not 02KFKDSF89SFMDFMFS7908934M90DODFSMN78345 K69SKLD04KCM62469933FA60567LLFD730957FA3 489FHDFS93MDF89UY2345905DFSKDDSKFDS9FSEF.
for i in $(seq 1 $NUMCRT);
do
let $i;
DEL="var$i"
echo "Delete number $DEL"
done
It should show echo "Delete number $DEL" in 2nd for loop value as below.
Delete number 02KFKDSF89SFMDFMFS7908934M90DODFSMN78345
Delete number K69SKLD04KCM62469933FA60567LLFD730957FA3
Delete number 489FHDFS93MDF89UY2345905DFSKDDSKFDS9FSEF

You don't need to run dsconfigad twice.
domain=''; machine='';
while IFS="=" read key val
do case "$key" in
"Active Directory Domain"*) domain=$( echo $val ) ;; # strip space
"Computer Account"*) machine=$( echo $val ) ;; # strip space
*) if [[ -n "$domain" ]] &&
[[ -n "$machine" ]]
then break
fi;;
esac
done < <( /usr/sbin/dsconfigad -show )
I can't find a good example of security find-identity -v including the verbose option, so I'm going to fake my way through this by using your command structure, though I'm still not going to use all-caps vars (don't do that).
declare -a crt=( $( security find-identity -v | grep $machine.$domain | awk '{ print $2}' ) )
Now the values are in the $crt[#] array, numerically indexed.
If you know the index of the one you want to remove,
unset "crt[$num]"
This does leave a hole in your array...
Alternately, use the values themselves as the keys, and you won't have to track the indexes and leave holes in your array.
declare -A crt=()
while read one
do crt[$one]=1
done < <( security find-identity -v | grep $HOST | awk '{ print $2}' ) )
Now you can remove it with
unset "crt[$val]" # assuming $val is the key
or walk through them with
for val in "${!crt[#]}"
do : something with the key...
done
Useful?
As always, folks please check me. I don't have either of these tools installed. Working blind and likely screwing something up. :)

Related

Check if read input is available in var

I try to list all Folders in /etc/nginx/html/.
I use this code:
folders=`for i in $(ls -d */ | grep -Ev "(backups)"); do echo ${i%%/}; done`
Now I get all folders with names non containing "backups".
Now I want to count the folder and save it into var. I use this code:
folders_count=( $folders )
echo ${#folders_count[#]}
It works. I get a list of all folders and I can count the folders.
Now I try to write a script that reads user input (or better, offers 1,2,3 choices, but I do not know how to do it) and install a script like Prestashop (as an example) into the folder the user has chosen if there are more than 1 folder.
Here is my code:
folders_count=( $folders )
echo ${#folders_count[#]}
echo
if [ ${#folders_count[#]} -gt 1 ]; then
echo "${info} Please choose a Website for Prestashop:" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
# for websites in $folders; do
# echo "${info} $folders" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
# echo "${info} $folders" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
# done
echo "$folders" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
#read websites_for_prestashop
read -e -i "$websites_for_prestashop" -p "Please enter your Website: " input
websites_for_prestashop="${input:-$websites_for_prestashop}"
if [ "$websites_for_prestashop" == "$folders" ]; then
echo "Website is $websites_for_prestashop"
else
echo "Website $websites_for_prestashop is not found"
fi
#echo "${info} Please choose a Website for Prestashop:" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
else
echo "nix"
fi
I dont know how I can make it work :/
Can anyone help me to fix it?
I would like to list the available folders. Then the user should be able to select in which folder he would like to install the script.
Folders:
[0] Folder 1
[1] Folder 2
[2] Folder 3
[3] Folder 4
....
Then a query will appear:
Please select an order for the installation:
The selection of the folder should then be stored in the variable read websites_for_prestashop
I do not know what your script is supposed to be doing. There are a bunch of lines commented out, the only assignment for websites_for_prestashop contains a reference to the variable itself and occurs after this variable is first used, and the script ultimately does nothing.
What I can tell you is that the way you extract filenames is not the right way to do it. Parsing the output of ls is not a good idea (see http://mywiki.wooledge.org/ParsingLs), and the way you do it will fail on any file with a name containing spaces, among other things.
This would be one way to do it:
declare -a folders=()
for f in */
do
[[ $f =~ backups ]] || folders+=("${f%/}")
done
echo "Folder count is: ${#folders[#]}"
Thank you for your help#
https://stackoverflow.com/users/2416376/olli-k
https://stackoverflow.com/users/7422249/fred
Solution is easy:
folders=`for i in $(ls -d */ | grep -Ev "(backups)"); do echo ${i%%/}; done`
echo "${info} Please choose a Website for Prestashop:" | awk '{ print strftime("[%H:%M:%S] |"), $0 }'
select websites_for_prestashop in $folders;
do
echo "You picked $websites_for_prestashop."
break
done

Why does my bash script hang?

I'm working on a bash script that will check +1000 domains if they are expired. I use a a for loop to iterate over all users in /var/cpanel/users/*. It works great for like the 10 first users (loops) then it just hangs.
A weird thing is that I can stop the script with Ctrl+Z and then start the script again with fg and it continues to work normal for about +10 users but then it hangs again.
This is my scirpt:
# File that will have the result.
file="domain-result.txt"
printf "USER\t\tDOMAIN\t\t\tREPORT\n" > "$file"
printf "\n" >> "$file"
# For loop to iterate over all users in cpanel.
for z in /var/cpanel/users/*;
do
# Only files can be used.
if [[ -f "$z" ]]
then
# Get the domain name.
awk -F'=' '/DNS=/ {print $2}' "$z" | while read row;
do
# If there's no domain name than skip to next account.
if [[ -z "$row" ]]; then continue; fi
printf "Checking domain: %s...done\n" "$row"
# Execute whois command on the domain.
whois=$( /usr/bin/whois $row | grep 'not found' )
# Get the username.
user=$( echo "$z" | awk -F'/' '{print $5}' )
if [[ -n "$whois" ]]
then
printf "%s\t\t%s\t\t%s - EXPIRED\n" "$user" "$row" "$whois" >> "$file"
break
else
continue
fi
done
else
continue
fi
done
printf "\n"
printf "Total: $( sed '1,2d' "$file" | wc -l ) expired domains.\n"
This is a sample of how the files in /var/cpanel/users/* look like:
DNS=stackoverflow.com
Thank you Ignacio Vazquez-Abrams for pointing out WHOIS abuse. I got it to work by adding a sleep 2 to the for loop. Now it works great.

Set variable from awk while parsing lines from a multiline file

I've got a txt file with several lines, each one describing a remote server, like this:
user#server:port:remote_working_path:whether_using_VPN
The : char separates the 4 fields.
I need to operate batch actions within each server, hence I need to parse each line and set appropriate variables. Right now, what I've coded is this:
while read server;
do
echo "$server" | awk -F ':' '{print $1}' &&
echo "$server" | awk -F ':' '{print $2}' &&
echo "$server" | awk -F ':' '{print $3}'
echo "$VPN"
declare $( echo "$server" | awk -F ':' '{print $VPN=$4}' )
echo 'VPN: '$VPN
done < $CUSTOMER_SERVERS_FILE
This script only prints the first 3 fields, and in my intentions should also set $VPN variable as the 4th field. However this seems way broken, and I'm being unable to fix it. How should I modify it so that $VPN = $4?
First, you don't need to use awk in this case. You could try to use something like :
while IFS=':' read -ra array; do
# "${array[0]}" => first field
# "${array[1]}" => second field
# ...
# "${array[#]}" => all fields
done < "$CUSTOMER_SERVERS_FILE"
Then if you want to set VPN variable with the 4th field, you could use :
while IFS=':' read -ra array; do
# ...
VPN="${array[3]}"
done < "$CUSTOMER_SERVERS_FILE"
Another solution :
while IFS=':' read -r address port path vpn trash; do
# The variables $adress $port $path and $vpn are assigned.
# $trash is set with other fields if there are more than 4 fields
done
Finally, when you want to assign the output of a command in a variable, you could do :
var="$(command)"
# or
var="`command`"

Extract a certain part of a string in bash with different patterns

I have this file:
CLUSTERS=SP1,SP2,SP3
FNAME_SP1="REWARDS_BTS_SP1_<GTS>.dat"
FNAME_SP2="DUMP_LOG_SP2_<GTS>.dat"
FNAME_SP3="TEST_CASE_TABLE_SP3_<GTS>.dat"
What I want to get from these are:
REWARDS_BTS_SP1_
DUMP_LOG_SP2_
TEST_CASE_TABLE_SP3_
I loop through the CLUSTERS field, get the values, and use it to find the appropriate FNAME_<CLUSTERNAME> value. Basically, the CLUSTERS value are ALWAYS before the _<GTS> part of the string. Any string pattern will do, provided that the CLUSTERS value come before the _<GTS> at the end of the string.
Any suggestions? Here's a part of the script.
function loadClusters() {
for i in `echo ${!CLUSTER*}`
do
CLUSTER=`echo ${i} | grep $1`
if [[ -n ${CLUSTER} ]]; then
CLUSTER=${!i}
break;
fi
done
echo -e ${CLUSTER}
}
function loadClustersCampaign() {
for i in `echo ${!BPOINTS*}`
do
BPOINTS=`echo ${i} | grep $1`
if [[ -n ${BPOINTS} ]]; then
BPOINTS=${!i}
break;
fi
done
for i in `echo ${!FNAME*}`
do
FNAME=`echo ${i} | grep $1`
if [[ -n ${FNAME} ]]; then
FNAME=${!i}
break;
fi
done
echo -e ${BPOINTS}"|"${FNAME}
}
#get clusters
clusters=$(loadClusters $1)
for i in `echo $clusters | sed 's/,/ /g'`
do
file=$(loadClustersCampaign ${i/-/_} | awk -F"|" '{print $2}') ;
echo $file;
#then get the part of the $file variable
done
Fun with Shell Parameter Expansions
You can use matching-prefix notation and indirect expansion to get at the variables you want, and use the "remove suffix" expansion on each result to collect just the portions of the filename that you want. For example:
FNAME_SP1='REWARDS_BTS_SP1_<GTS>.dat'
FNAME_SP2='DUMP_LOG_SP2_<GTS>.dat'
FNAME_SP3='TEST_CASE_TABLE_SP3_<GTS>.dat'
for cluster in "${!FNAME_SP#}"; do
echo ${!cluster%%<GTS>*}
done
This will print out the following:
REWARDS_BTS_SP1_
DUMP_LOG_SP2_
TEST_CASE_TABLE_SP3_
but you could issue any valid shell command inside the loop instead of using echo.
See Also
http://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
If you like an awk solution for this ,may be below will be useful.
> echo 'FNAME_SP1="REWARDS_BTS_SP1_<GTS>.dat"' | awk -F"<GTS>" '{split($1,a,"=\"");print substr(a[2],2)}'
REWARDS_BTS_SP1_
Furthur more detail below:
> cat temp
LUSTERS=SP1,SP2,SP3
FNAME_SP1="REWARDS_BTS_SP1_<GTS>.dat"
FNAME_SP2="DUMP_LOG_SP2_<GTS>.dat"
FNAME_SP3="TEST_CASE_TABLE_SP3_<GTS>.dat"
> awk -F"<GTS>" '/FNAME_SP/{split($1,a,"=");print substr(a[2],2)}' temp
REWARDS_BTS_SP1_
DUMP_LOG_SP2_
TEST_CASE_TABLE_SP3_
>

bash script and greping with command line

new to bash scripting so just wondering if i am doing this code right at all. im trying to search /etc/passwd and then grep and print users.
usage ()
{
echo "usage: ./file.sk user"
}
# test if we have two arguments on the command line
if [ $# != 1 ]
then
usage
exit
fi
if [[ $# < 0 ]];then
usage
exit
fi
# Search for user
fullname=`grep $1 /etc/passwd | cut -f 5 -d :`
firstname=`grep $1 /etc/passwd | cut -f 5 -d : | cut -f 1 -d " "`
#check if there. if name is founf: print msg and line entry
not sure as how to this or if im doing this right...
am i doing this right?
grep $1 /etc/passwd | while IFS=: read -r username passwd uid gid info home shell
do
echo $username: $info
done
This might work for you:
fullname=$(awk -F: '/'$1'/{print $5}' /etc/passwd)
firstname=${fullname/ *}
You're on the right track.
But I think the 2nd if [[ $# < 0 ]] .... fi block doesn't get you much. Your first test case gets the situation right, 'This script requires 1 argument or quits'.
Also, I don't see what you need firstname for, so a basic test is
case "${fullname:--1}" in
-[1] ) printf "No userID found for input=$1\n" ; exit 1 ;;
* )
# assume it is OK
# do what every you want after this case block
;;
esac
You can of course, duplicate this using "${firstname}" if you really need the check.
OR as an equivalent if ... fi is
if [[ "${fullname}" == "" ]] ; then
printf "No userID found for input=$1\n" ; exit 1
fi
note to be more efficient, you can parse ${fullname} to get firstname without all the calls to grep etc, i.e.
firstname=${fullname%% *}
Let me know if you need for me to explain :--1} and %% *} variable modifiers.
I hope this helps.
Instead of this:
fullname=`grep $1 /etc/passwd | cut -f 5 -d :`
firstname=`grep $1 /etc/passwd | cut -f 5 -d : | cut -f 1 -d " "`
Try this:
fullname=$(cut -f5 -d: /etc/passwd | grep "$1")
if [[ $? -ne 0 ]]; then
# not found, do something
fi
firstname=${fullname%% *} # remove the space and everything after
Note that I changed my answer to cut before grep so that it doesn't get false positives if some other field matches the full name you are searching for.
You can simply by reading your input to an array and then printing out your desired fields, something like this -
grep $1 /etc/passwd | while IFS=: read -a arry; do
echo ${arry[0]}:${arry[4]};
done
Test:
jaypal:~/Temp] echo "root:*:0:0:System Administrator:/var/root:/bin/sh" |
while IFS=: read -a arry; do
echo ${arry[0]}:${arry[4]};
done
root:System Administrator

Resources