0

I have a script which logs in to a server. Regardless of the success (i.e. whether the password is valid or not) the script will exit with return code 0, and the text:

Error login failed.

I'd like it to retry login if this happens by running another command, but because of the return code I can't.

If I pipe the output to grep for 'Error' so I can execute a command based on that then the login dialog doesn't show up in the terminal.

Is there anyway around this?

Pseudo code as this is for work:

loginCmd && echo "$?"
username:
password:

Error login failed. 
0

Update

I tried using an idea from a commentator, but I can't capture the text with 'Error' as that line occurs after the command completes...

Here's what it actually looks like, with incorrect password:

agent registration
username: xyz
password:

Error login failed.

I tried this:

result=$(loginCmd | tee /dev/tty)

grep -q 'Error' <<< "$result" && 
    loginCmd

The error string outputs after the command completes, so result doesn't capture it:

result=agent registration

So I guess there is no way to capture this string?

Error login failed.

Any ideas?

Ideally on login failure the script would return 1, or have some sort of retry mechanism, but it doesn't and I can't change that, it's a company script and this only affects the terminal, not the GUI which is what customers use.

19
  • Return code 0 usually means success, with non-zero codes indicating one of possibly several errors. Does your code really return zero on failure? Commented Jul 8 at 19:47
  • it's a login program at work, whether the login passes or fails it returns 0, I didn't create it, it's company software
    – Nickotine
    Commented Jul 8 at 19:57
  • 1
    so you don't really care about the return code after all, right? You want to re-run it when it returns zero after failing, but not when it returns after succeeding?
    – ilkkachu
    Commented Jul 8 at 19:58
  • 4
    you could build an expect script to "talk" with the login program, and maybe return a different exit status based on the output. Or cheaper and dirtier: loginCmd | tee tempfile and then grep error tempfile, but I suspect that will break somehow
    – ilkkachu
    Commented Jul 8 at 20:03
  • 1
    Your theory doesn’t make sense: loginCmd cannot output the error message after loginCmd completes.   Maybe it writes the error message to stderr, or maybe directly to the tty.   What happens if you run loginCmd 2> /dev/null?   How about result=$(loginCmd 2>&1 | tee /dev/tty)? Commented Jul 9 at 3:28

2 Answers 2

3

An solution might look like this

#!/usr/bin/env expect -f
set looping true
while {$looping} {
  spawn loginCmd
  interact {
    -o
    "Error Login failed." { puts "Try again"; return }
    "login successful"    { set looping false }
  }
}

Mixing shell and expect is basically a matter of invoking expect just like any other command. The tricky part is ensuring that the quoting is correct, and that expect variables are not inadvertently expanded by the shell

#!/usr/bin/env bash
echo "do some bash stuff first ..."

# a shell variable you want to use in expect, put it in the environment
export username="john doe"

# the expect code gets sent to expect on its stdin.
# a quoted heredoc quotes the whole document.
# shell variables are accessed through the expect `env` array.
expect << 'END_EXPECT'
    puts "hello $env(username)"

    set looping true
    while {$looping} {
      spawn loginCmd
      interact {
        -o
        "Error Login failed." { puts "Try again"; return }
        "login successful"    { set looping false }
      }
    }
END_EXPECT
14
  • 1
    That only works if the password is foobar I believe the OP wants a test for user that exist on the "Agent Registration" server regardless of password... Nice expect though.
    – eyoung100
    Commented Jul 9 at 17:57
  • can't do this as the loginCmd part is the last part of a bash script which has many functions doing other stuff, I only added it as that was the problem, also this isn't a script which does read it runs the company software, which has many parts, coupling it all. Yes exactly what @eyoung100 said
    – Nickotine
    Commented Jul 10 at 0:26
  • 1
    I'm not suggesting you replace your loginCmd with that little shell script. As I indicated, that was just to test the expect code. replace spawn loginCmd with spawn whatever you do to invoke your login command. It is straightforward to embed expect code in a shell script. Commented Jul 10 at 16:56
  • 1
    well actually the loop would continue so you'd get the message and loginCmd would be called again
    – Nickotine
    Commented Jul 11 at 16:21
  • 1
    Alternately, as expect is an extension of the general purpose language Tcl, you could write your whole script in expect. Tcl is quite a simple language it only has 12 rules. Commented Jul 11 at 16:49
1

This is a weird case and many thanks to everyone that helped sincerely. Many would've written it off just because of how strange or hard to communicate it was.

Props to Ikkachu (always a good contributer to my stuff) and G man.

Here's what I done:

while true; do
    result=$(loginCmd 2>&1 | tee /dev/tty)

    if grep -q 'Error' <<< "$result"; then
        loginCmd
    else
        break
    fi
done

Output:

agent registration
username: xyz
password: 
Error Login failed.
agent registration
username:xyz
password: 
login successful

It also didn't break getting the login right the first time.

I added the loop so it keeps prompting no matter how many times the password is entered wrong.

If anyone has any suggestions to make this better I'm open to it, I learned a lot here.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .