Format shell script output - linux

I am trying to format my script output in tabular format something like this:
Data: 11001,4071 | 10008,4578 | 10500,2100 ...
==================================================
20160720 55454 545454 55454
somehow i am able to achieve it but script asks for password and prints catrunner --> Using standard unix daf factory libpal-daf inline.
like:
Date: 11001,4071 | 10008,4578 | 10500,2100 | 40000,4021 | 10003,1102 | 11001,9230 | 10001,1001 | 40000,4020 | 10001,1102 | 10008,4569 | 10008,4568 | 10003,1200 | 40000,4006
======================================================================================================================================================================================
20160720 Password: // for switch user, how can i ommit password request?
su: incorrect password
catrunner --> Using standard unix daf factory libpal-daf //How can i get ride of this line?
13116
catrunner --> Using standard unix daf factory libpal-daf
9167
catrunner --> Using standard unix daf factory libpal-daf
Here is my script:
#!/bin/bash
clear
DT=`date +%Y%m%d`
Yesterday=$(date --date="-1 day" +"%Y-%m-%d")
CODES="$(< error_codes.txt)"
divider==============
divider1=$divider$divider$divider$divider$divider$divider$divider$divider$divider$divider$divider$divider$divider$divider
header="\n %-10s %8s %10s %21s\n"
width=43
echo " Date: " `sed -e :a -e '$!N; s/\n/ | /; ta' error_codes.txt`
echo $divider1;
printf "%s\t" $DT
su - adv
cd /advdata/datashareB/FFFF/continuousDownstream/` echo $Yesterday`
for CODE in $CODES; do
EventType=$(echo $CODE | cut -c1-5)
ErrorCode=$(echo $CODE | cut -c7-10)
eventExport -printEvents -file Run_`echo $fileName`*_*.tar -filter "ErrorCode=`echo $ErrorCode`;EventType=`echo $EventType`" -names -silent | wc -l
done
printf "$s\n"

Related

How to align the column in proper format fot the script output

I have script which works for me at least but the padding or say it markers for aligning or justifying the columns are not working good and i'm struggling to get the best solutions for it.
Below is the script which basically gets the Os Release version and Perl version running on the system.
if you look at the Result section the outer lining or markers which i defined are getting destorted .
Script:
#!/bin/bash
printf "\n"
marker=$(printf "%0.s-" {1..65})
printf "|$marker|\n"
printf "|%-10s | %-13s | %29s |\n" "Hostname" "RedHat Vesrion" "Perl Version"
printf "|$marker|\n"
remote_connect() {
target_host=$1
marker=$(printf "%0.s-" {1..65})
remote_data=($(
ssh -i ssh_prod "root#${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no "
rhelInfo=\$(cat /etc/redhat-release | awk 'END{print \$7}')
perlInfo=\$(rpm -qa | grep -i mod_perl)
echo \$rhelInfo \$perlInfo
"))
rhelInfo=${remote_data[0]}
perlInfo=${remote_data[1]}
if [[ $? -eq 0 ]]
then
printf "|%-10s | %-13s | %20s |\n" "$target_host" "$rhelInfo" "$perlInfo"
else
printf "|%-10s | %-13s | %20s |\n" "$target_host" "Unable to get the ssh connection"
fi
} 2>/dev/null
export -f remote_connect
< CVE-2011-2767-hostsList.txt xargs -P30 -n1 -d'\n' bash -c 'remote_connect "$#"' --
Result:
|-----------------------------------------------------------------|
|Hostname | RedHat Vesrion | Perl Version |
|-----------------------------------------------------------------|
|fsx9015 | | |
|fsx1258 | | |
|fsx1195 | | |
|fsx1063 | | |
|fsx1241 | 6.9 | mod_perl-2.0.4-12.el6_10.x86_64 |
|fsx1242 | 6.9 | mod_perl-2.0.4-12.el6_10.x86_64 |
|fsx1210 | 6.7 | mod_perl-2.0.4-12.el6_10.x86_64 |
|fsx1484 | 6.9 | mod_perl-2.0.4-12.el6_10.x86_64 |
Required:
|-----------------------------------------------------------------|
|Hostname | RedHat Vesrion| Perl Version |
|-----------------------------------------------------------------|
|fsx9015 | | |
|fsx1258 | | |
|fsx1195 | | |
|fsx1063 | | |
|fsx1241 | 6.9 | mod_perl-2.0.4-12.el6_10.x86_64 |
|fsx1242 | 6.9 | mod_perl-2.0.4-12.el6_10.x86_64 |
|fsx1210 | 6.7 | mod_perl-2.0.4-12.el6_10.x86_64 |
|fsx1484 | 6.9 | mod_perl-2.0.4-12.el6_10.x86_64 |
please help me understand or get a better way of doing it.
I'd suggest you don't try to start formatting until you have all the data at hand: each column should be as wide as the longest value in it.
Also, to make your code simpler, use column instead of the "fancy" table. I'm sure there's a utility that can draw ASCII table borders, but is it really necessary?
This version just prints comma-separated values from the ssh connections, then uses column to add the whitespace.
Note that I'm using a quoted heredoc for the code to send to the target host, which simplifies quoting.
#!/bin/bash
remote_connect() {
target_host=$1
if remote_data=$(
ssh -i ssh_prod "root#${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no <<'END_SSH'
rhelInfo=$(awk 'END{print $7}' /etc/redhat-release)
perlInfo=$(rpm -qa | grep -i mod_perl)
echo "$rhelInfo,$perlInfo"
END_SSH
)
then
echo "${target_host},${remote_data}"
else
echo "${target_host},?,?"
fi
} 2>/dev/null
export -f remote_connect
{
echo "Hostname,RedHat Version,Perl Version"
< CVE-2011-2767-hostsList.txt xargs -P30 -n1 -d'\n' bash -c 'remote_connect "$#"' --
} | column -s"," -t
You should use as simplistic as it could be, define your column alignment as per the requirement with the printf formatter..
try below, it should work , however i did not tested it.
#!/bin/bash
###########
printf "\n"
marker=$(printf "%0.s-" {1..73})
printf "|$marker|\n"
printf "| %-15s | %-15s | %-35s |\n" "Hostname" "RedHat Vesrion" "Perl Version"
printf "|$marker|\n"
remote_connect() {
target_host=$1
remote_data=($(
ssh -i /home/nxf59093/.ssh/ssh_prod "root#${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no "
rhelInfo=\$(cat /etc/redhat-release | awk 'END{print \$7}')
perlInfo=\$(rpm -qa | grep -i mod_perl)
echo \$rhelInfo \$perlInfo
"))
rhelInfo=${remote_data[0]}
perlInfo=${remote_data[1]}
if [[ $? -eq 0 ]]
then
printf "| %-15s | %-15s | %-35s |\n" "$target_host" "$rhelInfo" "$perlInfo"
else
printf "| %-15s | %-15s | %-35s |\n" "$target_host" "?" "?"
fi
} 2>/dev/null
export -f remote_connect
< CVE-2011-2767-hostsList.txt xargs -P15 -n1 -d'\n' bash -c 'remote_connect "$#"' --
printf "|$marker|\n"

How to fill the missing columns with some static values in if-else condition under a function call

How to put some values in the missing columns, as you guys see the below code is working but in the in else condition it not filling the column values.
What i need to do to put the somevalues in missing areas. Specially i want to fill like nologin?.
#!/bin/bash
###########
printf "\n"
marker=$(printf "%0.s-" {1..73})
printf "|$marker|\n"
printf "| %-15s | %-15s | %-35s |\n" "Hostname" "RedHat Vesrion" "Perl Version"
printf "|$marker|\n"
remote_connect() {
target_host=$1
remote_data=($(
ssh -i /home/nxf59093/.ssh/ssh_prod "root#${target_host}" -o StrictHostKeyChecking=no -o PasswordAuthentication=no "
rhelInfo=\$(cat /etc/redhat-release | awk 'END{print \$7}')
perlInfo=\$(rpm -qa | grep -i mod_perl)
echo \$rhelInfo \$perlInfo
"))
rhelInfo=${remote_data[0]}
perlInfo=${remote_data[1]}
if [[ $? -eq 0 ]]
then
printf "| %-15s | %-15s | %-35s |\n" "$target_host" "$rhelInfo" "$perlInfo"
else
printf "| %-15s | %-15s | %-35s |\n" "$target_host" "?" "?"
fi
} 2>/dev/null
export -f remote_connect
< CVE-2011-2767-hostsList.txt xargs -P15 -n1 -d'\n' bash -c 'remote_connect "$#"' --
printf "|$marker|\n"
Result:
|---------------------------------------------------------------|
|Hostname | RedHat Vesrion | Perl Version |
|---------------------------------------------------------------|
|fsx1241 | 6.9 | mod_perl-2.0.4-12.el6_10.x86_64 |
|fsx1242 | 6.9 | mod_perl-2.0.4-12.el6_10.x86_64 |
|fsx1243 | 6.9 | |
|fsx1244 | | |
|fsx1245 | | |
|---------------------------------------------------------------|
You should look at PARAMETER Expansion of Bash by using a default value. For an example, provide in the bash wiki page, for an example below ..
${PARAMETER:-WORD}
${PARAMETER-WORD}
Where, If the parameter PARAMETER is unset (never was defined) or null (empty), this one expands to WORD, otherwise it expands to the value of PARAMETER, as if it just was ${PARAMETER}. If you omit the : (colon), like shown in the second form, the default value is only used when the parameter was unset, not when it was empty.
Looking at your code, taking the above in consideration, your below line of code just need minor correction and that should do the Job for you.
if [[ $? -eq 0 ]];then
printf "| %-15s | %-15s | %-35s |\n" "$target_host" "$rhelInfo" "$perlInfo"
else
printf "| %-15s | %-15s | %-35s |\n" "$target_host" "${rhelInfo:-?}" "${perlInfo:-?}"
fi
You will get like below:
|---------------------------------------------------------------|
|Hostname | RedHat Vesrion | Perl Version |
|---------------------------------------------------------------|
|fsx1241 | 6.9 | mod_perl-2.0.4-12.el6_10.x86_64 |
|fsx1242 | 6.9 | mod_perl-2.0.4-12.el6_10.x86_64 |
|fsx1243 | 6.9 | |
|fsx1244 | ? | ? |
|fsx1245 | ? | ? |
|---------------------------------------------------------------|
hope this will be usefull.

Problem with putting value in array in bash

I would like to make array which put users in a time using for loop. For example:
y[1]="user1"
y[2]="user2"
...
y[n]="usern"
I tried to do it like this
#!/bin/bash
x=$(who | cut -d " " -f1 | sort | uniq | wc -l)
for (( i=1; i<=$x; i++ )); do
y[$i]=$(who | cut -d " " -f1 | sort | uniq | sed -n '$ip')
p[$i]=$(lsof -u ${y[$i]} | wc -l)
echo "Users:"
echo ${y[$i]}
echo -e "Number of launched files:\n" ${p[$i]}
done
Most likely I'm using command "sed" wrong.
Can you help me?
Indeed your sed command seems to be a bit off. I can't really guess what you're trying to do there. Besides that, I'm wondering why you're executing who twice. You can make use of the data first obtained in the following manner.
#!/bin/bash
# define two arrays
y=()
p=()
#x=0
while read -r username; do
y+=("$username")
p+=($(lsof -u $(id -u "$username") | wc -l))
echo -e "User:\n${y[-1]}"
echo -e "Open files:\n${p[-1]}"
# The -1 index is the last index in the array, but you
# could uncomment the x=0 variable and the line below:
#((x++))
done <<< $(who | cut -d " " -f1 | sort | uniq)
echo "Amount of users: $x"
exit 0

Can terraform plan show me a json diff for a changed resource?

When I run terraform plan it shows a changed resource, which happens to be JSON data in an aws_s3_bucket_object. But the JSON is long and it's difficult to see what changed. How can I display this as a diff?
https://github.com/coinbase/terraform-landscape can help with this.
gem install terraform_landscape (may need sudo on macOS)
terraform plan | landscape
This shows JSON changes as a diff. Here's an example from the github site:
I wrote a bash script to format terraforms ugly policy output:
#!/bin/bash
input=$( xclip -o )
old=$( echo "$input" | awk -F' => ' '{ print $1 }' | sed 's/\\n/\n\r/g' | sed 's/\\"/"/g' | sed 's/"{/{/' | sed 's/}"/}/' )
new=$( echo "$input" | awk -F' => ' '{ print $2 }' | sed 's/\\n/\n\r/g' | sed 's/\\"/"/g' | sed 's/"{/{/' | sed 's/}"/}/' )
echo "----------------------------------------------------------------------------------------------"
echo "old:"
echo "$old" | jq '.'
echo "----------------------------------------------------------------------------------------------"
echo "new:"
echo "$new" | jq '.'
echo "----------------------------------------------------------------------------------------------"
echo "diff:"
diff -u --color <( echo "$old" | jq '.' ) <( echo "$new" | jq '.' )
echo "----------------------------------------------------------------------------------------------"
It shows three blocks of output, the old, then the new and then the diff. It makes use of xclip, jq and diff. Usage is (on Linux) to highlight the terrafrom output and then invoke the script (I call it tf-diff and it lives in ~/bin).

batch file to read file contents and iterate

I am trying to write a batch file/shell script that reads the contents of a file, matches those contents with a directory structure and invokes an executable file.
Let's say there is a sequence.txt file in /system/ directory. The sequence file is to represent or force the order of execution. This is important
The sequence.txt file has following enteries:
1;schema1;procedures
1;schema1;functions
2;schema2;procedures
2;schema2;functions
........
and then there is a directory, and the directory has following subdirs
/scripts
| +--/schema1
| | +--/procedures
| | | --1.sql
| | | --2.sql
| | +--/functions
| | | --1.sql
| | | --2.sql
| | +--/packages
| | | --1.sql
| | | --2.sql
| | +--/logs
| +--/schema2
| | +--/procedures
| | | --1.sql
| | | --2.sql
| | +--/functions
| | | --1.sql
| | | --2.sql
| | +--/packages
| | | --1.sql
| | | --2.sql
| | +--/logs
.......
........
Now I would like to run flyway (a database migration software) in a loop using this way:
Flyway -schema=schema1 -locations=/scripts/schema1/procedures, /scripts/schema1/functions, /scripts/schema1/packages migrate -x | tee /scripts/schema1/log/logfile_ddmmyy.log
Flyway -schema=schema2 -locations=/scripts/schema2/procedures, /scripts/schema2/functions, /scripts/schema2/packages migrate -x | tee /scripts/schema2/log/logfile_ddmmyy.log
So far this is my progress:
#!/bin/bash
while read i;
do echo "$i";
done < ./system/sequence.txt
How can I proceed further? I know that this kind of scripting involves variables and then loops but I can't find a way to translate it into technical level.
Cheers and thanks in advance! :-)
Though not completely clear about what you want, here is some inspiration:
while read line; do
OIFS=$IFS
IFS=';'
a=()
for name in ${line}; do
a+=(${name})
done
IFS=$OIFS
number=${a[0]}
schema=${a[1]}
subdir=${a[2]}
echo "Flyway -schema=${schema} -locations=/scripts/${schema}/procedures, /scripts/${schema}/functions, /scripts/${schema}/packages migrate -x | tee /scripts/${schema}/log/logfile_ddmmyy.log"
done <<EOF
1;schema1;procedures
1;schema1;functions
2;schema2;procedures
2;schema2;functions
EOF
It doesn't exexute Flymake, it just echo the Flymake commands.
It uses the special variable $IFS to do the magic.
Fit it to your needs.
output
Flyway -schema=schema1 -locations=/scripts/schema1/procedures, /scripts/schema1/functions, /scripts/schema1/packages migrate -x | tee /scripts/schema1/log/logfile_ddmmyy.log
Flyway -schema=schema1 -locations=/scripts/schema1/procedures, /scripts/schema1/functions, /scripts/schema1/packages migrate -x | tee /scripts/schema1/log/logfile_ddmmyy.log
Flyway -schema=schema2 -locations=/scripts/schema2/procedures, /scripts/schema2/functions, /scripts/schema2/packages migrate -x | tee /scripts/schema2/log/logfile_ddmmyy.log
Flyway -schema=schema2 -locations=/scripts/schema2/procedures, /scripts/schema2/functions, /scripts/schema2/packages migrate -x | tee /scripts/schema2/log/logfile_ddmmyy.log
I am not sure about the exact relation betwen values and final command path but awk is the tool to construct the call. Use somethin like:
c = `echo $i | awk -F ";" '{print "flyway" $1 "_" $2}'
where $x is the position of the value and you can construct a string.
After that you can run the c var with
`echo $c`
That should work.
UPDATED:
If I understand correctly what you need, you have to set two whiles, one inside the other. Something like this:
cat tt.txt | awk -F";" '{print $1}'| sort -u | while read i
do
sc = `grep $i tt.txt | head -n 1 | awk -F";" '{print $2}'`
pt1 = "Flyway -schema=" $sc " -locations="
pt3 = " -x | tee /scripts/" $sc "/log/logfile_ddmmyy.log"
grep $i tt.txt | while read j
do
c=`echo $j | awk -F";" '{print $2}'| sort -u`
pt2 = $pt2 "/scripts/" $sc "/" $c ""
done
echo $pt1 $pt2 $pt3
done

Resources