From: Christopher on
I need some help with an expect script to remotely monitor for a login
on our PBX. Haven't touched expect in seven or eight years and cannot
find my copy of "The Book". The PBX has no tools (cron, at, mail, etc)
for me to run locally so I need to establish a single ssh session that
checks every five minutes if a login (for e911 service) is still
connected. This script loops correctly every five minutes if the login
is present but hangs and takes no further action (at the expect in
whogrep) if I change $login to something I know will fail the test.

#!/usr/bin/expect -f
#

set timeout -1
set remhost "somehost"
set login "somelogin"
set email "email(a)example.com"

proc connect {remhost} {
spawn ssh -q $remhost
expect "\$ " {
return
}
}

proc whogrep {login} {
send -- "who | grep $login\r"
expect -gl "*$login pts*\$ " {
return 0
}
return 1
}

proc alert {email} {
exec echo "$login not connected to PBX." | mailx -s "$login Login
Missing" $email
}

connect $remhost
while 1 {
sleep 300
set whostatus [ whogrep $login ]
if { $whostatus == 0 } {
continue
} else {
alert $email
continue
}
}

From: Bruce on
Christopher Caldwell wrote:
> I need some help with an expect script to remotely monitor for a login
> on our PBX. Haven't touched expect in seven or eight years and cannot
> find my copy of "The Book". The PBX has no tools (cron, at, mail, etc)
> for me to run locally so I need to establish a single ssh session that
> checks every five minutes if a login (for e911 service) is still
> connected. This script loops correctly every five minutes if the login
> is present but hangs and takes no further action (at the expect in
> whogrep) if I change $login to something I know will fail the test.
>

you've set the timeout to -1 which means wait forever for a match

your whogrep function is only looking for a positive match so it never
returns from the expect statement - you need to either a) set a timeout
so it falls out is user not found, or b) add a match pattern to the
expect statement of the prompt again and return a 0 in that case


> #!/usr/bin/expect -f
> #
>
> set timeout -1
> set remhost "somehost"
> set login "somelogin"
> set email "email(a)example.com"
>
> proc connect {remhost} {
> spawn ssh -q $remhost
> expect "\$ " {
> return
> }
> }
>
> proc whogrep {login} {
> send -- "who | grep $login\r"
> expect -gl "*$login pts*\$ " {
> return 0
> }
> return 1
> }
>
> proc alert {email} {
> exec echo "$login not connected to PBX." | mailx -s "$login Login
> Missing" $email
> }
>
> connect $remhost
> while 1 {
> sleep 300
> set whostatus [ whogrep $login ]
> if { $whostatus == 0 } {
> continue
> } else {
> alert $email
> continue
> }
> }
>
From: Christopher on
Thanks,

I've removed the timeout and the script appears to work. What would be
the best way to add the match pattern for a null result, which I'm
assuming is the cleaner way to fix the script? If I run the script in
debug the expect_out(buffer) gets set to "" when there is no match, but
if I replace:

proc whogrep {login} {
send -- "who | grep $login\r"
expect -gl "*$login pts*\$ " {
return 0
}
return 1
}

with the following to match expect_out I don't get a match. I assume I
would not want to return a 0 in any case, if I only want to set
whostatus to 0 if the login is present.

proc whogrep {login} {
send -- "who | grep $login\r"
expect -gl "*$login pts*\$ " {
return 0
}
"" {
return 1
}
}

On 2010-05-26 17:06:34 -0400, Bruce said:

> Christopher Caldwell wrote:
>> I need some help with an expect script to remotely monitor for a login
>> on our PBX. Haven't touched expect in seven or eight years and cannot
>> find my copy of "The Book". The PBX has no tools (cron, at, mail, etc)
>> for me to run locally so I need to establish a single ssh session that
>> checks every five minutes if a login (for e911 service) is still
>> connected. This script loops correctly every five minutes if the login
>> is present but hangs and takes no further action (at the expect in
>> whogrep) if I change $login to something I know will fail the test.
>>
>
> you've set the timeout to -1 which means wait forever for a match
>
> your whogrep function is only looking for a positive match so it never
> returns from the expect statement - you need to either a) set a timeout
> so it falls out is user not found, or b) add a match pattern to the
> expect statement of the prompt again and return a 0 in that case
>
>
>> #!/usr/bin/expect -f
>> #
>>
>> set timeout -1
>> set remhost "somehost"
>> set login "somelogin"
>> set email "email(a)example.com"
>>
>> proc connect {remhost} {
>> spawn ssh -q $remhost
>> expect "\$ " {
>> return
>> }
>> }
>>
>> proc whogrep {login} {
>> send -- "who | grep $login\r"
>> expect -gl "*$login pts*\$ " {
>> return 0
>> }
>> return 1
>> }
>>
>> proc alert {email} {
>> exec echo "$login not connected to PBX." | mailx -s "$login Login
>> Missing" $email
>> }
>>
>> connect $remhost
>> while 1 {
>> sleep 300
>> set whostatus [ whogrep $login ]
>> if { $whostatus == 0 } {
>> continue
>> } else {
>> alert $email
>> continue
>> }
>> }


From: Christopher on
I think I figured it out what you're saying, looking for the promt and
returning a 1 seems to work.

proc whogrep {login} {
send -- "who | grep $login\r"
expect -gl "*$login pts*\$ " {
return 0
}
"^\[*\$" {
return 1
}
}

On 2010-05-27 10:37:51 -0400, Christopher Caldwell said:

> Thanks,
>
> I've removed the timeout and the script appears to work. What would be
> the best way to add the match pattern for a null result, which I'm
> assuming is the cleaner way to fix the script? If I run the script in
> debug the expect_out(buffer) gets set to "" when there is no match, but
> if I replace:
>
> proc whogrep {login} {
> send -- "who | grep $login\r"
> expect -gl "*$login pts*\$ " {
> return 0
> }
> return 1
> }
>
> with the following to match expect_out I don't get a match. I assume I
> would not want to return a 0 in any case, if I only want to set
> whostatus to 0 if the login is present.
>
> proc whogrep {login} {
> send -- "who | grep $login\r"
> expect -gl "*$login pts*\$ " {
> return 0
> }
> "" {
> return 1
> }
> }
>
> On 2010-05-26 17:06:34 -0400, Bruce said:
>
>> Christopher Caldwell wrote:
>>> I need some help with an expect script to remotely monitor for a login
>>> on our PBX. Haven't touched expect in seven or eight years and cannot
>>> find my copy of "The Book". The PBX has no tools (cron, at, mail, etc)
>>> for me to run locally so I need to establish a single ssh session that
>>> checks every five minutes if a login (for e911 service) is still
>>> connected. This script loops correctly every five minutes if the login
>>> is present but hangs and takes no further action (at the expect in
>>> whogrep) if I change $login to something I know will fail the test.
>>>
>>
>> you've set the timeout to -1 which means wait forever for a match
>>
>> your whogrep function is only looking for a positive match so it never
>> returns from the expect statement - you need to either a) set a timeout
>> so it falls out is user not found, or b) add a match pattern to the
>> expect statement of the prompt again and return a 0 in that case
>>
>>
>>> #!/usr/bin/expect -f
>>> #
>>>
>>> set timeout -1
>>> set remhost "somehost"
>>> set login "somelogin"
>>> set email "email(a)example.com"
>>>
>>> proc connect {remhost} {
>>> spawn ssh -q $remhost
>>> expect "\$ " {
>>> return
>>> }
>>> }
>>>
>>> proc whogrep {login} {
>>> send -- "who | grep $login\r"
>>> expect -gl "*$login pts*\$ " {
>>> return 0
>>> }
>>> return 1
>>> }
>>>
>>> proc alert {email} {
>>> exec echo "$login not connected to PBX." | mailx -s "$login Login
>>> Missing" $email
>>> }
>>>
>>> connect $remhost
>>> while 1 {
>>> sleep 300
>>> set whostatus [ whogrep $login ]
>>> if { $whostatus == 0 } {
>>> continue
>>> } else {
>>> alert $email
>>> continue
>>> }
>>> }


From: Glenn Jackman on
In addition to Christopher's advice:


At 2010-05-26 03:33PM, "Christopher Caldwell" wrote:
> proc alert {email} {
> exec echo "$login not connected to PBX." | mailx -s "$login Login Missing" $email
> }

exec mailx -s "$login Login Missing" $email << "$login not connected to PDX."

The << argument to exec passes the value to the command on its stdin.

--
Glenn Jackman
Write a wise saying and your name will live forever. -- Anonymous