Image: jivacore/Shutterstock

Bash scripting remains a staple of my endeavors in Linux as a system administrator, and I use it every day to ease my workload. One of my most commonly used type of shell scripts involves a for-loop which processes and applies commands to servers based on a text file I’ve created containing the target host names.

SEE: Kubernetes: A cheat sheet (free PDF) (TechRepublic)

These scripts can copy files to servers or log into these systems via ssh to run various commands. This process is best utilized with SSH host keys in place to permit passwordless access to target systems otherwise you’ll have to type a password in for each system to which your script will connect. You must have the appropriate permissions to run these commands as well.

It cannot be overstated that your list of target hosts must be accurate and only contain systems upon which these commands should be run, otherwise you can very quickly wreak havoc by deleting files or rebooting hosts which shouldn’t be on this list. Rebooting production systems can be what we in IT call a CEE—career-ending event.

Note that these scripts must contain a .sh extension and be set to executable using chmod +x (script name). If the file name containing the list of servers is not in the same directory you’re running the script from you’ll need to specify the full path in the script. I usually run my scripts from a subfolder under “root.”

Here is an example of one of my simple scripts, “besrestart.sh.” This script is intended to start the besclient service (BigFix, used for system patching) on all the hosts listed in a text file called “servers”:

for l in `cat servers`; do echo $l;ssh -q $l service besclient restart;echo $l; done

The script uses “for I” as in a lowercase L (not to be confused with i or I), meaning to cat the servers text file and return one-by-one each host name to use to conduct the commands following the semi-colon. “I” simply refers to each host name entry. Each semi-colon separates the commands in the chain.

Note that ` is not a single quote; it is the “back quote” character and shares the same key as the tilde (~) in the upper left of a typical keyboard.

“do echo $l” will output the host name before it runs the next command.

Now comes the nitty-gritty, where ssh -q $l tells the script to ssh to the target host. It’s now on the remote box and can kick off the “service besclient restart” command.

The “echo $I” displays the hostname involved as a way of confirming the command ran successfully.

SEE: From start to finish: How to deploy an LDAP server (TechRepublic Premium)

Finally, “done” ends the command chain and moves on to the next system, or finishes running the script if there are no more systems to work on.

Let’s say your servers file contains these items:

server1
server2
server3
server4
server5

After the script runs you would see output similar to the following, assuming the system could connect to all the targets.

server1
server1
server2
server2
server3
server3
server4
server4
server5
server5

If you see a single entry for a host name, check to ensure connectivity to that host is working and try again.

Here is another sample script which connects to a system, stops a service, deletes a file, copies a new file to the system via scp, then starts the related service.

for l in `cat servers`; do echo $l;ssh -q $l service besclient stop;echo $l; done 
for l in `cat servers`; do echo $l;ssh -q $l rm -rf /var/opt/BESClient/besclient.config;echo l; done 
for l in `cat servers`; do scp besclient.config $l:/var/opt/BESClient/;echo $l; done 
for l in `cat servers`; do echo $l;ssh -q $l service besclient start;echo $l; done

In no particular order, here are the main scripts I rely upon for daily tasks:

This script can stop a service, remove the related rpms and then delete the app directory to clean up target systems:

for l in `cat servers`; do echo $l;ssh -q $l service besclient stop;echo $l; done 
for l in `cat servers`; do echo $l;ssh -q $l rpm -e BESAgent-9.5.10.79-rhe6.x86_64;echo $l; done 
for l in `cat servers`; do echo $l;ssh -q $l rpm -e BESAgent-9.5.3.211-rhe5.x86_64;echo $l; done 
for l in `cat servers`; do echo $l;ssh -q $l rm -rf /etc/opt/BESClient /var/opt/BESClient /opt/BESClient;echo $l; done 

This script gathers some hardware details from the target hosts which can be useful for inventorying systems:

 for l in `cat servers`; do echo $l;ssh -q $l dmidecode | grep -i serial;echo $l; done
 for l in `cat servers`; do echo $l;ssh -q $l lscpu | grep "CPU(s):";echo $l; done
 for l in `cat servers`; do echo $l;ssh -q $l lscpu | grep "Core(s) per socket:";echo $l; done
 for l in `cat servers`; do echo $l;ssh -q $l lscpu | grep "Socket(s):";echo $l; done 
 for l in `cat servers`; do echo $l;ssh -q $l free -h;echo $l; done 

This script copies another script to target systems /etc/cron.daily folders so these scripts will be executed every 24 hours:

 for l in `cat servers`; do ssh -q $l /etc/cron.daily/update-tools.sh; done 

This script sets the owner of a certain file on target systems to be “prod1”:

 for l in `cat servers`; do echo $l;ssh -q $l chown prod1:prod /fileData/fileroot/certs/interac.jks;echo $l; done 

This script tells all target hosts to run a yum update and not prompt to install packages:

 for l in `cat servers`; do ssh -q $l yum -y update; echo $l; done 

This script backs up the /etc/shadow file on all target hosts to the root directory:

 for l in `cat servers`; do echo $l;ssh -q $l cp /etc/shadow /root/shadow20210604;echo $l; done 

This script reboots all servers listed in the servers file:

 for l in `cat servers`; do ssh -q $l shutdown -r now; echo $l; done 

This script can come in handy to unmount an existing NFS volume then update /etc/fstab with a new NFS mount name and remount all volumes:

 for l in `cat servers`; do echo $l;ssh -q $l umount /clover;echo $l; done 
 for l in `cat servers`; do echo $l;ssh -q $l;sed -r -i 's|vnx-corp-nfs1|unity-corp-nfs01|' /etc/fstab;mount -a;echo $l; done 

This script can add a host file entry to target systems

 for l in `cat servers`; do ssh -q $l 'echo "10.18.12.33 github.devops.local" >> /etc/hosts'; echo $l; done 

Finally, this script can tell you the current uptime on all target hosts:

 for l in `cat servers`; do echo $l;ssh -q $l uptime;echo $l; done 

As you can see, the functionality of these scripts is limited only by your imagination. I hope these are helpful and that they ease your administrative workload.

Subscribe to the Data Insider Newsletter

Learn the latest news and best practices about data science, big data analytics, artificial intelligence, data security, and more. Delivered Mondays and Thursdays

Subscribe to the Data Insider Newsletter

Learn the latest news and best practices about data science, big data analytics, artificial intelligence, data security, and more. Delivered Mondays and Thursdays