2

I am connecting to a VPN via a simple bash script, that I would like to run on computer startup, thus, I need it to be fully automated. However, the script will run "openconnect --jupiper" and ask for my credentials afterwards (about 3-4 seconds later when it acquires a connection).

Id like to have it output my credentials after some text is found (fastest and more precise way) or after a set delay (dumb and less precise way).

Is there a way to output commands after a set delay or after some text (regex match for example) is returned?

  • selvakumar.me/… – Rui F Ribeiro Mar 2 '16 at 16:13
  • Openconnect for example allows for setting the credentials via single line command, as such, it might have been a poor example. However not all applications support this, as such, the question still applies. – Joao Carlos Mar 2 '16 at 16:15
3

To automate commands, I have used over the years expect. It is great to simulate an interactive session, either when dealing with stubborn commands that do require interactivity, or to interact with active devices or other servers on your network. I still use it to login to active equipment, and fetch some statistics and perform automatic backups.

Expect is a program that "talks" to other interactive programs according to a script. Following the script, Expect knows what can be expected from a program and what the correct response should be. An interpreted language provides branching and high-level control structures to direct the dialogue. In addition, the user can take control and interact directly when desired, afterward returning control to the script.

Using Expect Scripts to Automate Tasks

As an example, a expect script I wrote to test the POP service:

#!/bin/sh
# \
exec expect "$0" ${1+"$@"}

set force_conservative 0  ;# set to 1 to force conservative mode even if
                          ;# script wasn't run conservatively originally
if {$force_conservative} {
        set send_slow {1 .1}
        proc send {ignore arg} {
                sleep .1
                exp_send -s -- $arg
        }
}

set timeout -1
spawn telnet 127.0.0.1 110
match_max 100000
expect {
"Hello"    { send -- "USER user@domain.pt\r"; exp_continue
       }
"assword" { send -- "PASS password\r" ; exp_continue
       }
"logged"   {
         send -- "LIST 1\r" ; exp_continue
   }
-re "failed|denied"   { exit
       }
"OK 1" { send -- "QUIT\r"; }
}

As per my conversation bellow with @cas, I would also point out, that the simple regexp expect language subset is useful for short automations scripts/[very] rough prototypes, together with bash.

If there is a need to more convoluted handling of output, the interactive handling can/better be done with another programming language.

For instance, in python, pexpect, or even in C, using libexpect or miniexpect.

Lately with the devops movement, you also have got a whole host of new [and old] frameworks to automate system tasks such as Ansible, Puppet, Salt.

They do require however a learning curve, and more resources. I personally favor Ansible.

Ansible Tip: Running Interactive Scripts with Ansible

  • There are also expect-like modules/libraries for perl, python, and many other languages. IMO it's usually better to use one of these because expect itself is a single-purpose language that isn't worth investing much time to lean while perl, python and others are general purpose languages that are worth the time to learn. To start researching this, search for Expect.pm (or Net::Telnet, Net::SSH and many others) for perl or pexpect for python. – cas Mar 3 '16 at 1:33
  • It is simple enough to script some simple jobs in a few minutes; I also never invested much time on it for similar reasons. If needing to do more convulted things with the output or input, it is indeed worth using some language. I used C to extract data customer usage and ptovisioning stats in a cable provider environment – Rui F Ribeiro Mar 3 '16 at 6:12
  • yep, i've used expect many times myself....but it's not something i'd recommend for others to learn. If you don't already know expect and you're going to spend some time learning a programming/scripting language, it's better to learn a good general-purpose one. – cas Mar 3 '16 at 7:31
  • Expect is much like bash or other tools. Good for one shot a-couple of minutes scripts, and for prototyping. Expect for networking guys like me is a life safer for a quick tinkering with 2000 thousand cisco routers ;) – Rui F Ribeiro Mar 3 '16 at 9:05
  • I am updating the answer to the tune of this conversation. Nevertheless the question asks for how to do it via scripting/bash and in that case, it is really expect the right answer. – Rui F Ribeiro Mar 3 '16 at 9:15
1

I actually could not get "openconnect" to work correctly with all the command line arguments, so I ended up making a Expect script for it.

Rui F Ribeiro's answer was exactly on the money, however, I needed a little more research to get everything working, minor stuff, variables and such.

In the interest of who ever views this question here, I am posting the script that resolves my use-case for the original question, not because its an alternative but because it is an "extension" to Rui F Ribeiro's knowledge share.

#!/usr/bin/expect -f

set vpn_url "vpn.domain.com"
set vpn_username "theuser"
set vpn_password "thepassword"
set ubuntu_username "theubuntuloginuser"
set ubuntu_password "theubuntuloginpass"

set force_conservative 0  ;# set to 1 to force conservative mode even if
        ;# script wasn't run conservatively originally
if {$force_conservative} {
  set send_slow {1 .1}
  proc send {ignore arg} {
    sleep .1
    exp_send -s -- $arg
  }
}

set timeout -1
spawn $env(SHELL)
match_max 100000
send -- "sudo LD_LIBRARY_PATH=\"/usr/local/lib\" openconnect --juniper --no-cert-check $vpn_url -u $vpn_username\r"
expect {
  "password for $ubuntu_username:" {
    send -- "$ubuntu_password\r"
  }
}
expect -exact "password:"
send -- "$vpn_password\r"
expect eof
  • excellent news. mind you I gave a crude example for the sake of clarity. You can pass arguments, and often the string matching does not have to be exact, for instance I use assword, and it is not a typo. not dealing full string matching can be useful when dealing with slow devices or devices with configurable prompts. – Rui F Ribeiro Mar 3 '16 at 13:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.