Viscosity
Viscosity

Reputation: 321

How to code bash script to allow entire commands with spaces?

So basically, I'm looking for a way to make the below bash script work without an issue. Each of the commands actually works when tested individually, it's only in the actual script it has a problem. The code is below:

#!/bin/bash

answer="$(/usr/bin/grep "PermitRootLogin yes" /etc/ssh/sshd_config)"

  if [ $answer ]; then
       (perl -pi -e \'s/\"PermitRootLogin yes\"/\"PermitRootLogin no\"/g\' /etc/ssh/sshd_config)
 else
    echo "Root login is already not permitted, no values changed."
fi

Here's what happens when I try to run it:

test.sh:  line 9: [: PermitRootLogin: unary operator expected
Root login is already not permitted, no values changed.

So basically, rather than it doing the find/replace as I want it to on the file via the perl command, it's trying to interpret it as a separate instruction.

All it is attempting to do is look at the /etc/ssh/sshd_config file and then change the relevant entry from yes to no if the "answer" is found to be yes.

I'm basically looking for a way to make this work. I've looked at a lot of bash examples on this site but none of them seem to cover this specific case.

Also, the reason I'm using perl is that sed works very oddly on Solaris 11, or isn't installed on extremely old versions, and perl is installed on every version from 8 forward.

Any ideas?

Upvotes: 1

Views: 135

Answers (3)

user3458
user3458

Reputation:

Value of $(grep...) is the lines found by grep or empty string. Using those lines as argument to [ is not too useful.

Try

if /usr/bin/grep "PermitRootLogin yes" /etc/ssh/sshd_config >/dev/null; then

instead.

How does it work?

The actual syntax for if in bash (or sh, for that matter) is

if command args; then

When you use if [ ... ] syntax, all you do is use [ as an alias for test command (try running which [ on your machine).

if takes the then branch when command succeeds (has exit code of 0) and else branch when it fails - returns non-zero exit code.

grep succeeds when pattern is found, fails when not found.

Upvotes: 1

Sobrique
Sobrique

Reputation: 53478

You could just run the replace, because if it's not necessary, it won't match and it won't do anything.

This is exactly as efficient as greping the file first.

If you need a message, how about counting whether it actually did it:

perl -i.bak -pe '$result += s/PermitRootLogin yes/PermitRootLogin no/; END { exit 1 unless $result }' /etc/ssh/sshd_config

(Then test $? in your script).

Or:

perl -i.bak -pe '$result += s/PermitRootLogin yes/PermitRootLogin no/; END { print "Fixed permissions\n" if $result }' /etc/ssh/sshd_config

Upvotes: 1

choroba
choroba

Reputation: 241818

Double quote the variable in square brackets.

if [ "$answer" ] ; then

Otherwise, it's expanded and word-split, but [ doesn't know what to do with two words (it expects the first one to be a unary operator like -f which is what the error's telling you).

Upvotes: 2

Related Questions