简体   繁体   中英

Bash Grep Quiet SSH Output

I'm trying to match the output of an SSH command but for some reason it's not working. I'm using authorized_keys to restrict the login to one command - which is a wrapper script that takes parameters.

Here's my code:

for i in `seq 2 254`; do
  myoutput=$( ssh system@server01 ip 192.168.0.$i )
  echo "$myoutput"
  echo "$myoutput" | grep -q "not found"
  if [ $? -eq 0 ]; then
    echo 192.168.0.$i
    exit
  fi
done

Here's the output of the script:

192.168.0.2 not found in DB.  Try searching live (--forcelive)
192.168.0.3 not found in DB.  Try searching live (--forcelive)
192.168.0.4 not found in DB.  Try searching live (--forcelive)

This should stop at the first instance and echo the IP but it's continuing along because ALL of the greps are returning 1 rather than 0. The SSH command itself (without the grep) returns 0 every time.

Why is grep miscoding the response? Is there a better way to accomplish what I'm wanting to do?

The content you're trying to search for is almost certainly on stderr, so your substitution isn't capturing it at all; thus, it's being emitted to the console by the same command that invokes ssh rather than placed in the myoutput variable.

Consider using the redirection 2>&1 to redirect stderr to stdout, as so:

myoutput=$( ssh system@server01 "ip 192.168.0.$i" 2>&1 )

By the way, if you're okay with the overhead of calling ssh over two hundred times, I would seriously consider rewriting this like so:

for ((i=2; i<254; i++)); do
  if ssh system@server01 "ip 192.168.0.$i" 2>&1 | grep -q 'not found'; then
    echo "192.168.0.$i"
    exit
  fi
done

Why?

  • seq is neither built into bash, nor POSIX-specified. Thus, it's not guaranteed even to exist, much less to behave in any particular way.
  • The command line passed by ssh to a remote system is built as a single string generated by concatenating arguments. Passing only a single string with the exact code you wish to execute is thus a more honest representation of what goes on under the hood, and avoids bugs that can be created by forgetting what ssh really does with its command line.
  • Using $? is bad form when you can simply test for success of a command directly.

If you weren't restricted by authorized_keys , by the way, you'd be much better off moving the script evaluation to the remote system, something like:

ip_found=$(ssh system@server01 bash -s <<'EOF'
  for ((i=2; i<254; i++)); do
    content=$(ip "192.168.0.$i" 2>&1)
    if [[ $content = *"not found"* ]]; then
      echo "192.168.0.$i"
      exit 0
    fi
  done
  exit 1
EOF
)

echo "Remote system found $ip_found"

...since you are so restricted, you might -- for performance reasons -- consider using SSH multiplexing to reuse a single authenticated connection over your many queries.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM