ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm trying to start a script by pinging a host, and if the host is down I want to move on to the next host on the list:
Code:
#!/bin/bash
grep lf /etc/storelist | awk '{print $1}' > /tmp/lf-hosts
for STORE in `cat /tmp/lf-hosts`
do
echo ==========
echo $STORE
ping -c 1 $STORE > /dev/null 2>/dev/null
pingRet=$?
if [ $pingRet -eq 0 ]; then
start=0
elif [ $pingRet -eq 1 ]; then
echo Host down
exit
fi
if [ "$start" = '0' ]; then
ssh vision@$STORE "\
ls -l vision.cnf; \
grep EXT_CREDIT_UPC vision.cnf | wc -l; \
cp vision.cnf vision.cnf-newCreditMaps"
fi
done
Right now it's set up to exit the entire script if the store is down. What I want to do if the host is down is move on to the next host on the list instead of exiting the entire script.
$ man bash
...
break [n]
Exit from within a for, while, until, or select loop. If n is
specified, break n levels. n must be ≥ 1. If n is greater than
the number of enclosing loops, all enclosing loops are exited.
The return value is 0 unless n is not greater than or equal to
1.
If you're interested in a different approach, hear's a gawk script that searches my /etc/fstab for any mount directives for cifs files with a nofail option that are not mounted. If any such files are found, it searches for them on a set of predefined address ranges and mounts them when they are found, and updates a file in /etc with the found locations to be used for initialization for the next time the program is run.
I've highlighted the section of the code that does the search for the cifs file shares.
Code:
#!/usr/bin/gawk -f
###############################################################################
#
# Mount any available, unmounted, "nofail" cifs shares listed in /etc/fstab
#
# Note: This code reads from /etc/fstab, and ignores any input files.
#
###############################################################################
#
# Define the needed console code color setting values.
BEGIN {
_csi = "\x1b" "["
_reset = _csi "0m"
_bold = _csi "1m"
_red = _csi "31m"
_green = _csi "32m"
_brown = _csi "33m"
_blue = _csi "34m"
_magenta = _csi "35m"
_cyan = _csi "36m"
_white = _csi "37m"
}
#
# Set the default address in the pool to be scanned.
BEGIN {
if (!_pool) _pool= "192.168." # Base address block
if (!_in) _in= 1 # Look in the _pool._in address block
if (!_from) _from= 101 # Starting at _pool._in._from
if (!_to) _to= 110 # Ending with _pool._in._to
}
#
# Get the list of currently mounted files (Ignoring all non-device mounts.)
BEGIN {
while (getline res < "/proc/self/mounts") {
if (res ~ /^\//) {
nf=split(res,part)
if (nf > 1) mtab[gensub("\\\\040"," ","g",part[2])]++
}
}
close("/proc/self/mounts")
}
#
# Read in the domain_map file if it exists
BEGIN {
map[""]=""
delete map
while ((getline domain_map < "/etc/domain_map" )>0) {
if ("^[[:space:]]*#" ~ domain_map) continue
nf=split(domain_map,token,/[[:space:]]*=[[:space:]]*/)
if (nf != 2) continue
map[token[1]]=map[token[1]] (map[token[1]]?":":"") token[2]
}
close("/etc/domain_map")
}
#
# Make sure that /etc/fstab is in the input file list
BEGIN {
failed=1
for (i=0;i < ARGC; ++i) {
if (ARGV[i] == "/etc/fstab") {
failed=0
break
}
}
if (failed) {
ARGV[ARGC++]="/etc/fstab"
}
}
#
# Main loop: Parse /etc/fstab to find any unmounted "cifs nofail" shares, and attempt to mount them.
#
#Skip any comment line
/^[[:space:]]*\#/ {
next
}
# Remove any comments from the input line before trying to parse it.
{
sub(/[[:space:]]*#.*$/,"")
}
# Skip any blank line
((/^[[:space:]]*$/) || (length($0)==0)) {
next
}
# Is this a valid fstab entry?
(NF != 6) {
printf(" %sWarning: \"%s\" does not contain exactly 6 fields. Skipped.%s\n", _bold _red, $0, _reset) > "/dev/stderr"
next
}
# Does this line have a fs_type of "cifs" and a "nofail" somewhere in the option string?
(($3 == "cifs") && ($4 ~ "nofail")) {
gsub("\\\\040"," ",$2)
# Skip this one if it's already mounted
if (!($2 in mtab)) {
line[++lines]=$0
res=""
}
next
}
# O.K., /etc/fstab has been parsed. Do the mounting.
END {
count=length(line)
if (count > 0) {
printf("\n%sAttempting to mount %d device%s listed in /etc/fstab as \"cifs nofail\".%s\n",
_bold _blue,
count,
((count>1)?"s":""),
_reset)
}
else {
exit(0)
}
# Attempt to mount any unmounted "nofail cifs" file(s) using the /etc/fstab entry.
for (i in line) {
failed=Mount(line[i], mtab, "", map)
if (!failed) {
delete line[i]
++mounted
}
if (failed == 3) {
delete line[i]
}
}
# Do we have anything to do?
if (length(line) == 0) {
print " " _bold _green "No " (mounted?"other ":"") "unmounted \"nofail cifs\" devices were referenced in /etc/fstab." _reset > "/dev/stderr"
}
else {
# Process the lines that are left from /etc/fstab
#
# For each server in the specified range . . .
for (i=_from; i<=_to; ++i) {
# If the list is now empty, we're all done.
if (length(line) == 0) break
# Get the next URL to try
url=sprintf("%s%d.%d", _pool, _in,i)
print _bold _magenta " Trying " url _reset
# Try to mount any unmounted shares using this URL }
failed=""
for (j in line) {
failed=Mount(line[j], mtab, url)
if (!failed) {
# Remove this entry if it's successfully mounted.
++mounted
delete line[j]
# And try this URL on any remaining unmounted shares
for (k in line) {
failed=Mount(line[k], mtab, url)
if (!failed) {
++mounted
delete line[k]
}
}
}
}
}
}
# Create a new domain_map file if any mount attempts were successful.
if (mounted) {
subash="sudo bash "
print "echo '# Map of domain names to IP4 addresses' > '/etc/domain_map'" | subash
for (i in map) {
print "echo " i " = " map[i] " >> /etc/domain_map" | subash
}
close(subash)
}
# List any unmounted shares
if (length(line) > 0) {
printf(" %sNo server could be located from which the following shares could be mounted.\n%s", _bold _red, _reset)
for (j in line) {
split(line[j], part, /[[:space:]]+/)
printf(" %s%s%s\n", _bold _red, part[1], _reset)
}
}
}
#######################################################################################################################
#
# Attempt to mount a cifs share using a specific URL or the url specified in /etc/domain_map
#
# Note: If map is specified, this function will recusively call itself using the map values as URLs
#
#######################################################################################################################
# Return 0 if successful
# 1 if the mount point is already in use
# 2 if the URL is valid but the share name is not found on that URL
# 3 if called with an invalid fstab entry
# the URL if the URL is not valid (So we can skip trying it again.)
function Mount(\
line, # Line from /etc/fstab specifying a "cifs, noauto" mount\
mtab, # Array of mounted files\
# Optional arguments
url, # Url to try in place of the domain specified in /etc/fstab (if omitted, use the domain in fstab.)\
Map, # Map of symbolic domain names to IP4 addresses (see /etc/domain_map)\
# Note: If Map is not an array and the mount is successful, the global map
# array will be updated with the URL.
# Local variables
nf,i,j,k, # Working values (count, indices, etc.)\
part, # Whitespace delimited components of line.\
domain, # The domain specified in /etc/fstab\
mapped, # URLs to which a domain has been mapped\
ret, # Mount command return status\
error, # Parsed error array\
tmp) # Command return string(s) holder. (Note the -v option to the mount command.)
{
# Break the line from /etc/fstab into space delimited parts
nf=split(line, part, /[[:space:]]+/)
if (nf != 6) return 3
# Return without comment if this entry has already been mounted
if (part[2] in mtab) return 1
# Split the first part (the device) into '/' delimited parts. Assume that the first part is the domain name
split(part[1],domain,/\/+/)
# Do we have a replacement URL to use?
if (url) {
# Replace the domain with the URL
sub(domain[2],url,part[1])
}
# Make sure that the device string is terminated with a slash (to prevent share name collisions)
if (part[1] !~ "/$") part[1] = part[1] "/"
# Change the "nofail" option (if any) to "noauto" so we will get an error if the mount fails
gsub("nofail","noauto",part[4])
# Try to mount the share using the new URL (if any)
cmd="sudo mount -v -t " part[3] " -o " part[4] " " part[1] " " part[2] " &>/dev/stdout"
# Check for any errors or URL failure
ret=""
while (cmd|getline tmp) {
switch (tmp) {
case /Unable to find suitable address/:
case /could not resolve address/:
case /No such device or address/:
case /mount error/:
case /mount.cifs error/:
case /^[Ee]rror/:
close(cmd)
if (isarray(Map)) {
split(part[1],domain,/\/+/)
if (domain[2] in Map) {
nf=split(Map[domain[2]], mapped, ":")
for (i=1; i<=nf; ++i) {
failed=Mount(line, mtab, mapped[i])
if (!failed) {
return 0
}
}
}
}
return domain[2]
case /\W[Ee]rror\W/:
n=split(tmp, error, /[():][[:space:]]/)
if (n >3) {
ret=(ret?ret "\n" : "") "Error " error[2] ": " error[4]
}
else {
ret=(ret?ret "\n" : "") tmp
}
}
}
close(cmd)
# Did we get an error return from the (attempted) mount?
if (ret) {
# Print the failure reason
printf(" %sMount of %s from %s failed (%s).%s\n",_bold _red, part[2], part[1], ret, _reset)
# And return 2 so other mounts for this share will be attempted on the other URLs
return 2
}
# O.K., we've got a successful mount.
printf(" %sMounted %s from %s.%s\n", _bold _green, part[2], (url ? url : domain[2]), _reset)
# Update the mtab array
++mtab[part[1]]
# Update the global array, map, if this was a direct mount
if (!isarray(Map)) {
if (domain[2] in map && map[domain[2]] !~ url) {
map[domain[2]]=map[domain[2]] ":" url
}
else {
map[domain[2]]=url
}
}
return 0
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.