LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Expect syntax issue when calling a bash sed command that uses special character '}' (https://www.linuxquestions.org/questions/programming-9/expect-syntax-issue-when-calling-a-bash-sed-command-that-uses-special-character-%7D-4175421275/)

YortheHunter 08-09-2012 03:23 PM

Expect syntax issue when calling a bash sed command that uses special character '}'
 
Quick situational description :
I have an Expect script that is modifying dhcpd.conf by adding lines under a specific ip address. I want to make it more robust by having it check to be sure the lines I am looking to add are not already there by simply erasing everything between the ipaddress line and the '}' that closes that dhcp entry. I have the sed command that I would like Expect to issue once it is logged onto the dhcp server, but I cannot get the syntax correct for it to issue the command and have it complete correctly. Here is the Expect proc that is already executing sed commands to add the new lines :
($ip - passed in ip address)
($file - full pathname of dhcpd.conf)

spawn -noecho ssh $dhcpserver
expect "# " {send "sed -i '/$ip/a\ filename \"yaboot\";' $file\r\n"}
expect "# " {send "sed -i '/$ip/a\ next-server $tftpserver;' $file\r\n"}
expect "# " {send "/bin/systemctl restart dhcpd.service\r\n"}
expect "# " {send "exit\r\n"}
expect

This looks for an ip and then appends the filename and next-server lines underneath it. I would like to be able to check for any number of those lines aleady there and remove them first which I can accomplish with these sed commands :

sed -i '/IPADDRESS/,/^\}/ {/filename/d;}' dhcpd.conf
sed -i '/IPADDRESS/,/^\}/ {/next-server/d;}' dhcpd.conf

I have tested those sed lines and they do exactly what I want them to do, but the problem comes in when I try to issue them in Expect since the '}' is a special character. I have tried the following to no avail :

expect "# " {send "sed -i '/$ip/,/^\}/ {/filename/d;}' $file\r\n"}
expect "# " {send "sed -i '/$ip/,/^\}/ \{/filename/d;\}' $file\r\n"}
expect "# " {send "sed -i '/$ip/,/^\\\}/ {/filename/d;}' $file\r\n"}
expect "# " {send "sed -i '/$ip/,/^\\\}/ \{/filename/d;\}' $file\r\n"}

exec "sed -i '/$ip/,/^\}/ {/filename/d;}' $file\r\n"
exec "sed -i '/$ip/,/^\}/ \{/filename/d;\}' $file\r\n"
exec "sed -i '/$ip/,/^\\\}/ {/filename/d;}' $file\r\n"
exec "sed -i '/$ip/,/^\\\}/ \{/filename/d;\}' $file\r\n"

After the above attempts failed, I have attempted other ways to get expect to execute the sed commands to no avail. After a day and a half of abyssmal failures, I come to you....my goto guys. Hopefully it is just something simple that I am missing/lacking, in which case please beat me over the head with common sense so I can continue on to what I usually do everyday.....Try to take over THE WORLD....or whatever other sysadmin duties pop-up on my queue. Many thanks in advance

firstfire 08-10-2012 12:34 AM

Hi.

Welcome to LQ!

Please use the [CODE]..[/CODE] tags around code and data to preserve formatting.

What kind of error do you get? The first your command seems to work just fine for me:
Code:

$ cat exp
set file "in"
expect "#" {send "sed '1,/^\}/ {/filename/d;}' $file\r\n"}
$ echo '#' | expect exp
sed '1,/^}/ {/filename/d;}' in

No errors. So maybe the problem is in ssh or something else.

YortheHunter 08-10-2012 12:54 AM

Thanks for the fast reply. I'm home right now and decided to take a break from work tonight, so I'll get ya some more info tomorrow. However, some of the send commands would run with no error, but they would not modify the file. I should have been more clear about that on my original post. The intent is to modify dhcpd.conf only in the range from the ip to the closing curly brace and to remove any lines with filename or next-server in them before adding bot a new filename and next-server line. So if your command seemed to work, please be sure of modified the file correctly as well. I have been checking my scripts on a different machine against a copy of the dhcpd.conf file and then checking the file right after. As for the commands that gave errors, ill supply that tomorrow when I get to work. Thanks again for the early response, and sorry for the lack of info.....I tried not to miss anything, but was in a rush to get outta the office to lest my wife and daughter for dinner.

<2012-08-10 8AMish>
I also noticed that you are going from what looks like the beginning of the file. It probably doesn't matter for test purposes, but just thought I would point that out since that isn't really an option for me as it could potentially erase all the other 'filename' and 'next-boot' lines in my dhcpd.conf up to the specified ip (which is unacceptable)
=]

YortheHunter 08-10-2012 08:21 AM

Ok, so here is the double escape of the '}' :
Code:

#!/usr/bin/expect -f
#
set systemip [lindex $argv 0]
set dhcpfile [lindex $argv 1]
log_user 1
exp_internal 1
set expect_out(buffer) {}

proc check_for_preexisting_install_lines {ip file} {
        spawn bash
        send_user "ip is $ip and file is $file\r\n"
        expect "# " {send "sed -i '/$ip/,/\\\}/ {/filename/d}' $file\r\n"}
        expect "# " {send "sed -i '/$ip/,/\\\}/ {/next-server/d}' $file\r\n"}
}
###################### Execution ###################
check_for_preexisting_install_lines $systemip $dhcpfile
###################### Execution ###################

That returns with :
[root@servo ppxe-work]# ./test-proc-dhcp-check-for-recent-install2.exp x.x.x.x dhcptest.txt
spawn bash
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {11140}
ip is x.x.x.x and file is dhcptest.txt

expect: does "" (spawn_id exp6) match glob pattern "# "? no
[root@servo ppxe-work]#
expect: does "\u001b_root@servo:/temp/under-test/ppxe-work\u001b\[root@servo ppxe-work]# " (spawn_id exp6) match glob pattern "# "? yes
expect: set expect_out(0,string) "# "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\u001b_root@servo:/temp/under-test/ppxe-work\u001b\[root@servo ppxe-work]# "
send: sending "sed -i '/x.x.x.x/,/\}/ {/filename/d}' dhcptest.txt\r\n" to { exp6 }

expect: does "" (spawn_id exp6) match glob pattern "# "? no
sed -i '/x.x.x.x/,/\}/ {/filename/d}' dhcptest.txt

expect: does "sed -i '/x.x.x.x/,/\}/ {/filename/d}' dhcptest.txt\r\n" (spawn_id exp6) match glob pattern "# "? no
[root@servo ppxe-work]#
[root@servo ppxe-work]#
expect: does "sed -i '/x.x.x.x/,/\}/ {/filename/d}' dhcptest.txt\r\n\u001b_root@servo:/temp/under-est/ppxe-work\u001b\[root@servo ppxe-work]# \r\n\u001b_root@servo:/temp/under-test/ppxe-work\u001b\[root@servo ppxe-work]# " (spawn_id exp6) match glob pattern "# "? yes
expect: set expect_out(0,string) "# "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "sed -i '/x.x.x.x/,/\}/ {/filename/d}' dhcptest.txt\r\n\u001b_root@servo:/temp/under-test/ppxe-work\u001b\[root@servo ppxe-work]# "
send: sending "sed -i '/x.x.x.x/,/\}/ {/next-server/d}' dhcptest.txt\r\n" to { exp6 }

******* End Error ********
However, even though it says it ran when you look at the dhcptest.txt at the ip section that was specified it still has both lines in it (will post in next comment)

YortheHunter 08-10-2012 09:00 AM

Code:

#!/usr/bin/expect -f
#
set systemip [lindex $argv 0]
set dhcpfile [lindex $argv 1]
log_user 1
exp_internal 1
set expect_out(buffer) {}

proc check_for_preexisting_install_lines {ip file} {
        spawn bash
        send_user "ip is $ip and file is $file\r\n"
        expect "# " {send "sed -i '/$ip/,/\\\}/ {/filename/d}' $file\r\n"}
        expect "# " {send "sed -i '/$ip/,/\\\}/ {/next-server/d}' $file\r\n"}
        expect "# " {send "exit\r\n"}
        expect
}
###################### Execution ###################
check_for_preexisting_install_lines $systemip $dhcpfile
###################### Execution ###################

Works.....I must have gone cross eyed from staring at the same part of code for hours on end and had some other lingering typo. Many thanks for the second pair of eyes there firstfire. Koodo's to you. I will wander back to my cave now and beat myself mercilessly for wasting your time. Those responsible for flogging those that need to be flogged will also be flogged.

*sigh*

My sanity thanks you firstfire

YortheHunter 08-10-2012 09:02 AM

also, I posted another comment just before that last that stated that the results were unexpected as the filename was indeed gone, but the next-server line was still there. That pointed to needing an additional expect, thus my last comment with the funtional code. I must really need some sleep....thanks again guys

firstfire 08-10-2012 09:31 AM

Hi.

I'm glad to see you figured this out. Good luck!


All times are GMT -5. The time now is 03:35 PM.