I've written a function to do some logging on different aspects of the files, folder, etc and I 'm going to have this automatically email members of my staff. All this is fine but I wouldn't mind some pointers and help to make the formation nicer - this will get sent out via mailutils as part of the script.
Just looking for some nice spacing tips,etc
function report(){
lsb_release -a
echo "OS: $(uname -s)"
echo "ARCH: $(uname -m)"
echo "VER: $(uname -r)"
echo "Apache running "
ps aux|grep -i apache2
echo "Showing if SSL is open"
apache2ctl -M | grep ssl
echo "Space on local disk"
df -h
echo "Showing permissions for the web folders"
echo $'*** /var/www// ***'
ls -l /var/www | awk '{print $1 " " $3 " " $4 " " $9}'
ls -l /var/www/user1 | awk '{print $1 " " $3 " " $4 " " $9}'
ls -l /var/www/user2 | awk '{print $1 " " $3 " " $4 " " $9}'
echo "Showing network status"
ifconfig eth0
echo " DNS "
tail /etc/resolv.conf
echo "Current workspaces set up on the local server "
grep user2 /var/www/temp/text.txt | grep -E -o '[0-9]+[0-9]'
}
Try piping the "column" command instead of or after using awk or cut.
ls -l | awk '{print $1" "$3" "$4" "$9}' | tail -n +2 | column -t
Check out the difference between "mount" and "mount | column -t" or "df -PH and df -PH | column -t"
If you want to concatenate columns of info with the same number or relational fields you can use process redirection and "paste."
paste -d ' ' <(cat /sys/class/scsi_host/host*/device/fc_host:host*/port_name) \
<(cat /sys/class/scsi_host/host*/device/fc_host:host*/speed) \
<(cat /sys/class/scsi_host/host*/device/fc_host:host*/port_state)
0x218000e05a0001aa 4 Gbit Online
0x218000e05a2001aa 4 Gbit Online
Related
When ran commands locally on the remote server outputs would work as expected:
desired_kernel_version="5.4.0-105-generic"
cat /tmp/grb.bkp | grep GRUB_DEFAULT
GRUB_DEFAULT=0
kernel_position=$(awk -F\' '$1=="menuentry " || $1=="submenu " {print i++ " : " $2}; /\tmenuentry / {print "\t" i-1">"j++ " : " $2};' /boot/grub/grub.cfg | grep "${desired_kernel_version}" | grep -v recovery | awk '{ print $1}' | sed 's/ //g')
echo $k_position
1>2
sed -i "s/GRUB_DEFAULT=0/GRUB_DEFAULT=\"${k_position}\"/g" /tmp/grb.bkp
cat /tmp/grb.bkp | grep GRUB_DEFAULT
GRUB_DEFAULT="1>2"
desired output when ran from remote server:
replace 0 of GRUB_DEFAULT value to kernel_position within quotes.
server=abcd
kernel_position=$(ssh -qT $server awk -F\' '$1=="menuentry " || $1=="submenu " {print i++ " : " $2}; /\tmenuentry / {print "\t" i-1">"j++ " : " $2};' /boot/grub/grub.cfg | grep "${desired_kernel_version}" | grep -v recovery | awk '{ print $1}' | sed 's/ //g')
ssh -qT $server "sed -i "s/GRUB_DEFAULT=0/GRUB_DEFAULT=\"${k_position}\"/g" /tmp/grb.bkp"
Suggesting to avoid quoting hell.
Send muli-line command into ssh by writing a script remote-script.sh with all lines.
remote-script.sh
#!/bin/bash
source ~/.bash_profile
$k_position=$1
desired_kernel_version="5.4.0-105-generic"
cat /tmp/grb.bkp | grep GRUB_DEFAULT
GRUB_DEFAULT=0
kernel_position=$(awk -F\' '$1=="menuentry " || $1=="submenu " {print i++ " : " $2}; /\tmenuentry / {print "\t" i-1">"j++ " : " $2};' /boot/grub/grub.cfg | grep "${desired_kernel_version}" | grep -v recovery | awk '{ print $1}' | sed 's/ //g')
echo $k_position
1>2
sed -i "s/GRUB_DEFAULT=0/GRUB_DEFAULT=\"${k_position}\"/g" /tmp/grb.bkp
cat /tmp/grb.bkp | grep GRUB_DEFAULT
GRUB_DEFAULT="1>2"
Give current user execution permissions on remote-script.sh
chmod u+x remote-script.sh
Use scp command to copy remote-script.sh to $server. If possible only once at deploy time.
scp -q remote-script.sh $server:/home/your-user
Use ssh command to run remote-script.sh on remote server. Pass $k_position in command line.
ssh -qT $server "bash -c /home/your-user/remote-script.sh $k_position"
BTW, in computing kernel_position, suggesting to fold all awk, grep, sed commands into a single awk script.
I'd like to change my script(s) so that the command output is separated by a comma and is all on one line per host. Any ideas on how I can achieve this:
1st Script:
#!/bin/bash
for i in `cat ~/hostnames.txt`
do
ssh -q $i 'bash -s' < server_info.sh
done
2nd Script (server_info.sh):
#!/bin/bash
echo -n "Name: "
uname -n
echo -n "CPUs: "
cat /proc/cpuinfo* | grep processor | wc -l
echo -n "Memory (kb): "
cat /proc/meminfo | grep MemTotal: | awk '{print $2}'
echo -n "Current Kernel: "
uname -a | awk '{print $3}'
echo -n "IP: "
hostname -i
echo -e
Changing your 1st script:
#!/bin/bash
for i in cat ~/hostnames.txt
do
ssh -q $i 'bash -s' < server_info.sh
done | awk -v RS= '{$1=$1}1'
Note: Your server_info.sh can be a lot more optimized.For example:
cat /proc/meminfo | grep MemTotal: | awk '{print $2}'
could be changed to:
awk '/MemTotal:/{print $2}' /proc/meminfo
The output of $ip coming blank
#!/bin/bash
for i in illinrcmsg{002..003}
do
echo " ####################### $i #################### "
ssh -o StrictHostKeyChecking=no $i "
echo $i
cp /etc/hosts /etc/hosts_bak
ip=`ifconfig | head -n 2 | tail -n 1 | awk '{print $2}' | cut -d':' -f2`
echo $ip
echo "$ip $i.corp.amdocs.com $i" >> /etc/hosts
"
done
I am trying to fix /etc/hosts entry on multiple servers with a bash script, but it is dumping on hostname values on the file.
This worked:
#!/bin/bash
for i in illinrcmsg{002..003}
do
echo " ####################### $i #################### "
ssh -o StrictHostKeyChecking=no $i "
echo $i
cp /etc/hosts /etc/hosts_bak
#ip=`ifconfig | head -n 2 | tail -n 1 | awk '{print $2}' | cut -d':' -f2`
#echo $ip
echo "`nslookup illinrcmsg002 | tail -n 2 | head -n 1|awk '{print $2}'`
$i.corp.amdocs.com $i" >> /etc/hosts
"
done
I want changes_summary to always be in format <x> files changed, <y> insertion(+), <z> deletions(-) where <x> <y> and <z> are some numbers, but diffstat misses insertions and/or deletions part if <y> and/or <z> is zero, I tried to make it print as <x> files changed 0 insertion(+), 0 deletions(-) always, is there a better or easy way to do this? I would like to change $changes_summary variable so I can use it later part of the script.
changes_summary=`diff -ur ./dir1 ./dir2 | diffstat | tail -1`
if ! echo $changes_summary | grep -q "insertions" && ! echo $changes_summary | grep -q "deletions" ; then
echo $changes_summary | awk '{print $1 " " $2 " " $3 " " "0 insertion(+)," " " "0 deletions(-)"}'
elif ! echo $changes_summary | grep -q "insertions" && echo $changes_summary | grep -q "deletions" ; then
echo $changes_summary | awk '{print $1 " " $2 " " $3 " " "0 insertion(+), "$4 " " $5 }'
elif echo $changes_summary | grep -q "insertions" && ! echo $changes_summary | grep -q "deletions" ; then
echo $changes_summary | awk '{print $1 " " $2 " " $3 " " $4 " " $5 "0 deletions(-)" }'
fi
Probably the closest you can get without some serious bash magic or an other language is something like the following.
changes_summary=`diff -ur ./dir1 ./dir2 | diffstat -s`
CC=$(echo "$changes_summary" | sed -n 's:\(.*[0-9]\+ .* changed\).*:\1:p')
II=$(echo "$changes_summary" | sed -n 's:.*\([0-9]\+ insertions\?\).*:\1:p')
DD=$(echo "$changes_summary" | sed -n 's:.*\([0-9]\+ deletions\?\).*:\1:p')
echo "${CC}, ${II:-0 insertions}(+), ${DD:-0 deletions}(-)"
Sed strips out the message corresponding to each stat. The -n suppresses the normal output, p prints only if a match is found. If not, then CC, II, DD will be empty, in which case the ${II:-...} pattern substitutes a default value.
From man bash:
${parameter:-word} Use Default Values. If parameter is unset or null,
the expansion of word is substituted. Otherwise, the value of
parameter is substituted.
Note that keeping the (s) with s\? might be an overkill for you.
The other option is that in bash you can check for containment with [[ $a =~ "b" ]] and use your original approach. It spares you the greps at least and "b" here can also be regex if you drop the quotes.
if ! [[ "$changes_summary" =~ "insert" ]]; then
awk ...
fi
You can also find the =~ in man bash.
I'm using awk to parse /etc/hosts and produce a command which will format MapR for me. It's being done in a bash utility in Chef:
egrep '^[0-9]' /etc/hosts | grep -v 127.0.0.1 \
| awk 'NR==1{ips=$1}
NR>1{ips=ips ", " $1}
$2=="namenode"{nn=$1}
END{ printf "/opt/mapr/server/configure.sh -C %s -Z %s -N mycluster --create-user -D /dev/xvdb\n", ips, nn}' \
| bash
sleep 60
The command above should execute the following command:
/opt/mapr/server/configure.sh -C 10.32.237.251 -Z 10.32.237.251 -N mycluster --create-user -D /dev/xvdb
However, looking into my chef output I see:
==> namenode: Executing awk utility
==> namenode: awk: line 1: runaway string constant "/opt/mapr/ ...
The command never got executed in the MapR node... However when i execute it directly on the terminal it works nicely in the way it's supposed to be. What am I doing wrong?
I'm updating the question to show the complete bash script that executes that utility:
DISK_CONFIG=/home/ubuntu/disk_config
if [ -f $DISK_CONFIG ];
then
echo "File already exists"
else
echo "Executing awk utility\n"
touch $DISK_CONFIG
egrep '^[0-9]' /etc/hosts | grep -v 127.0.0.1 \
| awk 'NR==1{ips=$1}
NR>1{ips=ips ", " $1}
$2=="namenode"{nn=$1}
END{ printf "/opt/mapr/server/configure.sh -C %s -Z %s -N mycluster --create-user -D /dev/xvdb\n", ips, nn}' \
| bash
sleep 60
fi
Assuming you're using HEREDOC syntax in your bash resource:
bash "whatever" do
code <<-EOH
DISK_CONFIG=/tmp/disk_config
if [ -f $DISK_CONFIG ];
then
echo "File already exists"
else
echo "Executing awk utility\n"
touch $DISK_CONFIG
egrep '^[0-9]' /etc/hosts | grep -v 127.0.0.1 \
| awk 'NR==1{ips=$1}
NR>1{ips=ips ", " $1}
$2=="namenode"{nn=$1}
END{ printf "/opt/mapr/server/configure.sh -C %s -Z %s -N mycluster --create-user -D /dev/xvdb\n", ips, nn}' \
| bash
fi
EOH
end
this one leads to your error:
Executing awk utility
awk: line 4: runaway string constant "/opt/mapr/ ...
This is due to the \n in your comand (the one into the awk command is likely to be problematic too)
This resource should do (warning I did replace the DISK_CONFIG path for my tests):
bash "whatever" do
code <<-EOH
DISK_CONFIG=/tmp/disk_config
if [ -f $DISK_CONFIG ];
then
echo "File already exists"
else
echo "Executing awk utility"
touch $DISK_CONFIG
egrep '^[0-9]' /etc/hosts | grep -v 127.0.0.1 \
| awk 'NR==1{ips=$1}
NR>1{ips=ips ", " $1}
$2=="namenode"{nn=$1}
END{ printf "/opt/mapr/server/configure.sh -C %s -Z %s -N mycluster --create-user -D /dev/xvdb", ips, nn}' \
| bash
sleep 60
fi
EOH
end
The reason is that Chef already interpret the \n in the code and so awk see a string never ending (runaway).
As you pipe to bash you can omit the \n as the pipe will end the line.