1

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?

1
  • 1
    You've got an answer on the problem with the [ test command. FIxing that will show problems with the Perl. There's no obvious reason for using a sub-shell. And the quoting is bizarre and won't work. You need something like: perl -pi -e 's/"PermitRootLogin yes"/"PermitRootLogin no"/g' /etc/ssh/sshd_config (which assumes that the double quotes appear in the config file; if they don't, simply remove the double quotes from the command line). Commented Oct 22, 2015 at 15:01

3 Answers 3

2

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).

Sign up to request clarification or add additional context in comments.

1 Comment

That's one problem; the perl command is a mess too, though (but the code hasn't run into that yet — and won't until this is fixed).
1

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

Comments

1

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.

2 Comments

You can use grep -q instead of the redirection.
Assuming Solaris grep supports that option. :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.