Using Functions inside here document

2019-09-09 19:07发布

问题:

I have a script which has a few functions inside it which the main body uses to execute. Now, I want to run this script on 3 remote unix machines. Which is the neatest way to do this ? Most importantly, I don't to write a second script for remote connection. Everything should be inside this one script.

I've tried heredoc with ssh, which is not working because of the big functions !

Code -

#!/bin/bash

# Year Month Day Related functions
# FUNCTIONS
# Find no. of days in a year
yeardays()
{
# argument check
if [ X$1 = X ]
then
        read year
else
        year=$1
fi
# Check for leap years
if [ `expr $year % 400` = 0 ]
then
        echo 366
        exit
fi

if [ `expr $year % 100` = 0 ]
then
        echo 365
        exit
fi

if [ `expr $year % 4` = 0 ]
then
        echo 366
        exit
fi

echo 365
}

# Find no. of days in a Month
monthdays()
{
# argument check
if  [ X$1 = X ]
then
     read ymd   # year in yyyymmdd format
elif [ X$2 = X ]
then
      ymd=$1
else
      ymd=`expr \( $1 \* 10000 \) + \( $2 \* 100 \) + 1`
fi

year=`expr $ymd / 10000` ;
month=`expr \( $ymd % 10000 \) / 100` ;

case $month in
      1|3|5|7|8|10|12) echo 31 ; exit ;;
      4|6|9|11) echo 30 ; exit ;;
      *) ;;
esac

# except for month 2, which depends on whether the year is a leap year
# Use yeardays to get the number of days in the year and return a value
# accordingly.
daysInYear=`yeardays $year`

case $daysInYear in
   365) echo 28 ; exit ;;
   366) echo 29 ; exit ;;
esac
}

ymd2yd()    # convert from YYYYMMDD(gregorian) to YYYYDDD(julian)
{
# argument check
if [ X$1 = X ]
then
        read date
else
        date=$1
fi

year=`expr $date / 10000`
month=`expr \( $date % 10000 \) / 100`
days=`expr $date % 100`

count=1
while [ `expr $count \< $month` = 1 ]
do
        daysInMonth=`monthdays $year $count`
        days=`expr $days + $daysInMonth`
        count=`expr $count + 1`
done

julian=`expr \( $year \* 1000 \) + $days`
echo $julian
}

yd2ymd()    # convert from YYYYDDD(julian) to YYYYMMDD(gregorian)
{
# argument check
if [ X$1 = X ]
then
        read date
else
        date=$1
fi

year=`expr $date / 1000`
days=`expr $date % 1000`

month=1
while [ `expr $days \> 0` = 1 ]
do
        daysInMonth=`monthdays $year $month`
        days=`expr $days - $daysInMonth`
        month=`expr $month + 1`
done

days=`expr $days \+ $daysInMonth`
month=`expr $month \- 1`

gregorian=`expr \( $year \* 10000 \) + \( $month \* 100 \) + $days`
echo $gregorian
}

ydadd()     # Add/Subtract days to YYYYDDD format
{
# argument check
if [ X$2 = X ]
then
        difference=$1
        read yd     # Read the YYYYDDD format date
else
        yd=$1
        difference=$2
fi

days=`expr $yd % 1000`
year=`expr $yd / 1000`

days=`expr $days + $difference`
daysInYear=`yeardays $year`

while [ `expr $days \> $daysInYear` = 1 ]
do
        days=`expr $days - $daysInYear`
        year=`expr $year + 1`
        daysInYear=`yeardays $year`
done

while [ `expr $days \< 1` = 1 ]
do
        year=`expr $year - 1`
        daysInYear=`yeardays $year`
        days=`expr $days + $daysInYear`
done

yd=`expr \( $year \* 1000 \) + $days`       # Final date in YYYYDDD format
echo $yd
}

ymdadd()    # Add/Subtract days to YYYYMMDD format
{
if [ X$2 = X ]
then
        difference=$1
        read ymd    # Read YYYYMMDD format date
else
        ymd=$1
        difference=$2
fi

echo $ymd | ymd2yd | ydadd $difference | yd2ymd # Convert YYYYMMDD to YYYYDDD, perform date arithmetic, then revert to YYYYMMDD format
}

daysLeft()  # Calculate days between two dates in YYYYMMDD format
{
# argument check
if [ X$1 = X ]
then
        read ymd1   # First date in YYYYMMDD format
        read ymd2   # Second date in YYYYMMDD format
elif [ X$2 = X ]
then
        ymd1=$1
        read ymd2
else
        ymd1=$1
        ymd2=$2
fi

year1=`expr $ymd1 / 10000`
month1=`expr \( $ymd1 % 10000 \) / 100`
day1=`expr $ymd1 % 100`

year2=`expr $ymd2 / 10000`
month2=`expr \( $ymd2 % 10000 \) / 100`
day2=`expr $ymd2 % 100`

daysm1=`monthdays $year1 $month1`
days=`expr $daysm1 - $day1`
month1=`expr $month1 + 1`

while [ `expr $month1 \<= 12` = 1 ]
do
        daysm1=`monthdays $year1 $month1`
        days=`expr $days + $daysm1`
        month1=`expr $month1 + 1`
done

x=1
while [ `expr $x \< $month2` = 1 ]
do
        daysm2=`monthdays $year2 $x`
        days=`expr $days + $daysm2`
        x=`expr $x + 1`
done

days=`expr $days + $day2`
echo $days
}

# MAIN BODY
# Connect to different Servers
declare -a SERVER=('server1' 'server2' 'server3')
remoteUser=abc
serverNumbers=${#SERVER[@]}
count=0
while [ `expr $count \< $serverNumbers` = 1 ]
do
    # Connect to  server
    ssh -T -q $remoteUser@${SERVER[count]} <<-"END_TEXT"
    VALUE=`cat /home/cognos/cognos/c8/configuration/cogstartup.xml | grep -i xsd:long | head -1 | cut -d">" -f2 | sed 's/[:/<|crn:value]*//g'`
    VALUE_BACKUP=$VALUE
    let 'VALUE -= 30'       
    let 'VALUE *= 86400'
    RESULT1=`perl -e '@stats = stat("/home/cognos/cognos/c8/configuration/signkeypair"); print ((time - $stats[9]) < "$VALUE");'`
    RESULT2=`perl -e '@stats = stat("/home/cognos/cognos/c8/configuration/encryptkeypair"); print ((time - $stats[9]) < "$VALUE");'`
    RESULT3=`perl -e '@stats = stat("/home/cognos/cognos/c8/configuration/caSerial"); print ((time - $stats[9]) < "$VALUE");'`
    while [ "$RESULT1" -o "$RESULT2" -o "$RESULT3" ]
    do
            echo "Sending mail."
            # Calculate days left
            CURRENT_DATE=`date +"%Y-%m-%d" | sed 's/-//g'`
            CREATION_DATE=`ls -logE /home/cognos/cognos/c8/configuration/ | grep -i signkeypair | awk '{print $4}' | sed 's/-//g'`
            EXPIRY_DATE=`ymdadd $CREATION_DATE $VALUE_BACKUP`
            DAYS_LEFT=`daysLeft $CURRENT_DATE $EXPIRY_DATE`
            # Identify environment from hostname - DEV/UAT/PRD
            LOCALHOST=`hostname`
            ENVIRONMENT_TYPE=`echo $LOCALHOST | perl -ne '~m/.*([a-zA-Z]{3})[0-9]*$/; print $1;'|tr '[a-z]' '[A-Z]'`
            # Identify process - FormPF/GoReporting
            if (echo $LOCALHOST | grep -i cfp >/dev/null) then
                   PROCESS="FormPF"
            else
                   PROCESS="GoReporting"
            fi
            # Add details to mail body
            echo "The key was created on `ls -log /home/cognos/cognos/c8/configuration/ | grep -i signkeypair | awk '{print $4,$5,$6}'`, and was set to expire after $VALUE_BACKUP days." > mail.txt
            echo "Key expires in $DAYS_LEFT days !!" >> mail.txt
            echo " " >> mail.txt
            echo "The server is-" >> mail.txt
            hostname >> mail.txt
            echo " " >> mail.txt
            echo "Status of folders/files-" >> mail.txt
            echo " " >> mail.txt
            ls -log /home/cognos/cognos/c8/configuration/ | grep -i signkeypair | awk '{print $4,$5,$6,$7}' >> mail.txt
            ls -log /home/cognos/cognos/c8/configuration/ | grep -i encryptkeypair | awk '{print $4,$5,$6,$7}' >> mail.txt
            ls -log /home/cognos/cognos/c8/configuration/ | grep -i caSerial | awk '{print $4,$5,$6,$7}' >> mail.txt
        echo " " >> mail.txt
        echo "To reactive key, please restart the server at weekend with below options:" >> mail.txt
        echo " " >> mail.txt
        echo "/home/cognos/etc/restartAllServers.sh -cdsk" >> mail.txt
            # Send warning mail !!
            SUBJECT="!! ($ENVIRONMENT_TYPE) $PROCESS ($LOCALHOST) Cognos CSK(Common Symmetric Key) Expiry !!"
            EMAIL="xyz@abc.com"
            cat mail.txt | mailx -s "$SUBJECT" "$EMAIL"
        rm mail.txt
            break
    done
    logout
    END_TEXT
    count=`expr $count + 1`
done
exit 0

回答1:

Move the functions inside the heredoc. It may require some changes to the code structure but it will work.

ssh app01.datacentre.private <<EOD
hostdatefunc () {
echo \$(hostname) \$(date)
}
hostdatefunc
EOD

You'll get the hostname and date on the remote server, not yours. Works. Stupid example, but proof of concept.



标签: bash shell unix