help writing a bash script

smary
smary used Ask the Experts™
on
Please take a look at this script and help me edit it. Here's what I'd like to do:

Here's what the file I'm searching looks like:


**************************
**************************
*some stuff here

blah bhal

exclude /some/dir
eclude /foo
..
..

include /some/dir
include /some/other/stuff
include /yet/other/dir
..
..

I want to edit my current code so that if the string 'exclude /smary' is found in the file then do nothing and go to other machine. If the string is not found then append the string above all the include statements. Sometimes there might not be any exclude statements. In any case always append above all the include statements.

Also I'd like to add some kind of logging to the script. It logs the change made on every file on every host..

Here's a link to my previous question on EE:
http://www.experts-exchange.com/Programming/Languages/Scripting/Shell/bash/Q_25072625.html
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Author

Commented:
sc
sc.txt

Commented:
your question is resolved?
Anyhow, if you add 'exclude /smary' to right above 'include', you can use
if [ -z "`egrep -i "exclude /smary" $INCL_CHECKFILE]`" ]; then
    cp $INCL_CHECKFILE /tmp/backup;  
    awk '{add=0; if ( add=0 && $0 ~ /include/) {$0 = "exclude /smary\n"$0; add=1} {print}}' /tmp/backup > $INCL_CHECKFILE
    rm -f /tmp/backup;
else
    continue
fi

Commented:
The code is resemble to the previous Q. use the same auto_ssh.exp.
and let me know if it works for you
#!/bin/sh

HOST_LIST_FILE=file.txt
USER_NAME=user
USER_PASSWD=pass
EXIST_FILE=/the/remote/exist/file

LOG_FILE=/log/file

EXCLUDE_PATTERN="exclude /smarty"

function write2log()
{
echo $(date '+%m.%d.%Y-%H:%M:%S'): $*
} >> $LOG_FILE

for hostname in $( awk -F: '{print $1;}'  ${HOSTS_LIST_FILE} ); do
        auto_ssh.exp $USER_NAME  $USER_PASSWD $hostname 0 ls $EXIST_FILE
        if [ $? ne 0 ]; then
                write2log $hostname : $EXIST_FILE [Not exist]
        else
                auto_ssh.exp $USER_NAME  $USER_PASSWD $hostname 1 grep "${EXCLUDE_PATTERN}" $EXIST_FILE
                if [ $? eq 0 ]; then
                        # you can remove the following log msg if it not needed 
                        write2log $hostname : $EXIST_FILE [Exist] - ${EXCLUDE_PATTERN}  [ Already Exist ] - do nothing
                else
                        tf=tempfile
                        auto_ssh.exp $USER_NAME  $USER_PASSWD $hostname 0 cat ${EXIST_FILE} | awk -vexclude_dir_name="${EXCLUDE_PATTERN}" 'BEGIN{ exclude_flag=0 printed=0 } /^exclude/{exclude_flag=1;}  ! /^exclude/ && exclude_flag==1 && printed==0 {printed = 1; printf( "%s\n" ,  exclude_dir_name); } /^include/ && printed==0 { printed=1; printf("%s\n", exclude_dir_name); } {print $0;}' > $tf

                        
                        auto_ssh.exp $USER_NAME  $USER_PASSWD $hostname 2 $tf ${EXIST_FILE}

                        # to be more safe you can use the following instead
                        #cat $tf | auto_ssh.exp $USER_NAME  $USER_PASSWD $hostname 0 cat ${EXIST_FILE}.tmp
                        #auto_ssh.exp $USER_NAME  $USER_PASSWD $hostname 1 rm ${EXIST_FILE}
                        #auto_ssh.exp $USER_NAME  $USER_PASSWD $hostname 2 ${EXIST_FILE}.tmp ${EXIST_FILE}
                        rm $tf
                        write2log $hostname : $EXIST_FILE [Exist] - ${EXCLUDE_PATTERN} [Added]

                fi
        fi
done

Open in new window

Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

Author

Commented:
How do I execute this script?
I tired ./sshscript remotescript and it gave an error.
I guess I still have to give IP address to run this script?

Author

Commented:
I always get an error when I try to run this..
Please let me know how to run this properly..
If I still get error, then there might be something
wrong with the code..

Commented:
please upload the print outs.
that should include the command line you use as well.
if you made changes to the code - public the code you are using as well

Author

Commented:
Attached are the files.
I've actually changed the script.

Here's the error message:

[smary@newzealend ]$ ./autossh.exp smary pass egypt script1.bash  
command name "lrnage"
while executing
 "lrnage $argv 0 0"
 invoked from within
 "set user [lrnage $argv 0 0]"
 (file "./autossh.exp" line 6)

I actually tried with few diff ways, but got an error every time.

I appreciate your help in resolving this error.
autossh.txt
script.txt
Typo - "lrnage $argv 0 0"  should be "lrange $argv 0 0".  The others are all OK.

Author

Commented:
Sorry, tht was a typo and I mistakenly uploaded that error. Actually I tired it many different ways and got different error, so forgot which one is the right error. Here is another error:


[smary@newzealand ]$ ./autossh.exp smary pass script1.bash
wrong # args: no script following " $mode eq "1" " argument
    while executing
"if { $mode eq "1" }"
    (file "./autossh.exp" line 15)
It's a layout thing!  Languages like C don't really care about whitespace - commands can extend over several lines, or several comamnd can appear on a line with breaks anywhere in the command.  Expect is less forgiving!

The main problem was that the opening brace of the command (the "spawn" line, for example) has to appear on the same line as the closing brace of the "if" statement, so things like:
   if { $mode eq "0"} {
       spawn ........
   } else {
        if { $mode eq "0" } {
            spawn...
        }
   }

(also makes it easier to follow the logic!)

The attached code is a modified autossh.exp, with the lrnage and /dev/numm typos fixed too.
#!/usr/bin/expect -f
# Author: Arnon Kaufman
# based on    http://bash.cyberciti.biz/security/expect-ssh-login-script/
#  ./sshe.exp <user> <password> <ipaddress> <mode>  <remote script/command> <remote command args>
# ------------------------------------------------------------------------
# Copyright (c) Arnon Kaufman
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------

set user [lrange $argv 0 0]
set password [lrange $argv 1 1]
set ipaddr [lrange $argv 2 2]
set mode [lrange $argv 3 3]
set remote_command [lrange $argv 4 4]
set args [lrange $argv 5 end]
#set timeout -1


if { $mode eq "1" } {
       spawn ssh $user@$ipaddr $remote_command $args
} else {
       if { $mode eq "0" } {
               spawn ssh $user@$ipaddr $remote_command $args ">/dev/null 2>&1; echo $?"
       } else {
               if { $mode eq "2" } {
                       spawn scp $remote_command $user@$ipaddr:$args
               }
       }
}

match_max 100000
expect "*?assword:*"
send -- "$password\r"
send -- "\r"

if { $mode ne "0" } {
       expect {
               "0" { exit 0; }
               eof { exit 1; }
       }
} else {
       expect eof
}

Open in new window

Author

Commented:
That kinda works.
My question is how do I execute this script? Do I have to give the host and mode everytime I run this script? then whats the point of having the script if I have to run it 100 times for hundred hosts?
You still run the script.txt that you posted earlier, the one which starts:
    #!/bin/sh

    HOST_LIST_FILE=file.txt
    USER_NAME=user
    USER_PASSWD=pass

That script calls autossh.exp for each host listed in your /home/smary/test_current.txt.

There is one error in my autossh.exp - the line

    if { $mode ne "0" } {

8 lines from the end should be

    if { $mode eq "0" } {

I think the intention is that for mode 0 you run a command remotely, and if the return code from that command is 0 (for success), you return 0 from autossh.exp, otherwise you return 1.  For modes 1 and 2, the return code is 0 if the remote command could be run, even if the command itself failed.
Commented:
sorry for not be online for long time
anyway the autossh.exp expect to get more params - user pass ip mode and command, command parameters are optional

that is why the autossh refused to run correctly.

the assumption according to the question is that you have the same use/password for all the hosts in the list - otherwise you will have to adjust the host list file to include as fields the user and password. then you could split those fields in the main loop. and set the variables USER and PASS accordingly

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial