user3188544
user3188544

Reputation: 1631

Cleaner way to write multiple sed commands?

Is there a more DRY way to write the following commands (will be putting them in a bash shell script):

sudo sed -i 's/^#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config

sudo sed -i 's/^#PermitEmptyPasswords yes/PermitEmptyPasswords no/' /etc/ssh/sshd_config
sudo sed -i 's/PermitEmptyPasswords yes/PermitEmptyPasswords no/' /etc/ssh/sshd_config

sudo sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config

sudo sed -i 's/^#X11Forwarding yes/X11Forwarding no/' /etc/ssh/sshd_config
sudo sed -i 's/X11Forwarding yes/X11Forwarding no/' /etc/ssh/sshd_config

Upvotes: 11

Views: 2910

Answers (8)

eng27
eng27

Reputation: 916

Just a small comment.

Beautiful solution is suggested here (from ask Ubuntu).

Instead of writing same character twice in a single line, we can revise it as

sed -i '/^#PermitRootLogin/s/yes/no/' /etc/ssh/sshd_config

This approach will reduce mistakes based on typos.

Upvotes: 1

SimonTek
SimonTek

Reputation: 1

Being lazy, but I would just do this:

sed -Ei 's/.*PermitRootLogin yes|#PermitRootLogin no/PermitRootLogin no/g' /etc/ssh/sshd_config
sed -Ei 's/.*PermitEmptyPasswords yes|#PermitEmptyPasswords no/PermitEmptyPasswords no/g' /etc/ssh/sshd_config
sed -Ei 's/.*PasswordAuthentication yes|#PasswordAuthentication no/PasswordAuthentication no/g' /etc/ssh/sshd_config
sed -Ei 's/.*X11Forwarding yes|#X11Forwarding no/X11Forwarding no/g' /etc/ssh/sshd_config

~SimonTek

Upvotes: 0

NeronLeVelu
NeronLeVelu

Reputation: 10039

On standard unix (wher sed is posix and not GNU)

sed -e 's/^#PermitRootLogin yes/PermitRootLogin no/;s/PermitRootLogin yes/PermitRootLogin no/;s/^#PermitEmptyPasswords yes/PermitEmptyPasswords no/;s/PermitEmptyPasswords yes/PermitEmptyPasswords no/;s/^#PasswordAuthentication yes/PasswordAuthentication no/;s/PasswordAuthentication yes/PasswordAuthentication no/;s/^#X11Forwarding yes/X11Forwarding no/;s/X11Forwarding yes/X11Forwarding no/' /etc/ssh/sshd_config > /tmp/sshd_config
cat /tmp/sshd_config > /etc/ssh/sshd_config 
rm /etc/ssh/sshd_config 

normaly it's ok but line sometime define to start with the # than word and sometime no specification of place so a PermitRootLogin substitute also change a SpecialPermitRootLogin

Upvotes: 0

Cole Tierney
Cole Tierney

Reputation: 10314

You could put your sed commands in an external file:

sudo sed -i -f commands.sed /etc/ssh/sshd_config

commands.sed:
s/#*PermitRootLogin yes/PermitRootLogin no/
s/#*PermitEmptyPasswords yes/PermitEmptyPasswords no/
s/#*PasswordAuthentication yes/PasswordAuthentication no/
s/#*X11Forwarding yes/X11Forwarding no/

You can also embed a multiline sed script in a bash script:

#!/bin/bash

sudo sed -i '
    s/#*PermitRootLogin yes/PermitRootLogin no/
    s/#*PermitEmptyPasswords yes/PermitEmptyPasswords no/
    s/#*PasswordAuthentication yes/PasswordAuthentication no/
    s/#*X11Forwarding yes/X11Forwarding no/
' /etc/ssh/sshd_config

Upvotes: 1

dboals
dboals

Reputation: 610

Like I said you could also use a for loop.

#!/bin/bash

FILE='/etc/ssh/sshd_config'
REPLACE_STRINGS=('s/^#PermitRootLogin yes/PermitRootLogin no/' 's/PermitRootLogin yes/PermitRootLogin no/' 's/^#PermitEmptyPasswords yes/PermitEmptyPasswords no/' 's/PermitEmptyPasswords yes/PermitEmptyPasswords no/' 's/^#PasswordAuthentication yes/PasswordAuthentication no/' 's/PasswordAuthentication yes/PasswordAuthentication no/' 's/^#X11Forwarding yes/X11Forwarding no/' 's/X11Forwarding yes/X11Forwarding no/')


for i in "${REPLACE_STRINGS[@]}"
{
    sudo sed -i "$i" $FILE
}

Upvotes: 4

Jonathan Leffler
Jonathan Leffler

Reputation: 753930

Either use multiple -e 'sed-command' arguments in a single invocation of sed:

sudo sed -i.bak \
         -e 's/^#PermitRootLogin yes/PermitRootLogin no/' \
         -e 's/PermitRootLogin yes/PermitRootLogin no/' \
         -e 's/^#PermitEmptyPasswords yes/PermitEmptyPasswords no/' \
         -e 's/PermitEmptyPasswords yes/PermitEmptyPasswords no/' \
         -e 's/^#PasswordAuthentication yes/PasswordAuthentication no/' \
         -e 's/PasswordAuthentication yes/PasswordAuthentication no/' \
         -e 's/^#X11Forwarding yes/X11Forwarding no/' \
         -e 's/X11Forwarding yes/X11Forwarding no/' \
         /etc/ssh/sshd_config

Or create a script file, sed.script, containing the commands:

s/^#PermitRootLogin yes/PermitRootLogin no/
s/PermitRootLogin yes/PermitRootLogin no/
s/^#PermitEmptyPasswords yes/PermitEmptyPasswords no/
s/PermitEmptyPasswords yes/PermitEmptyPasswords no/
s/^#PasswordAuthentication yes/PasswordAuthentication no/
s/PasswordAuthentication yes/PasswordAuthentication no/
s/^#X11Forwarding yes/X11Forwarding no/
s/X11Forwarding yes/X11Forwarding no/

and then run sed with that file:

sudo sed -i.bak -f sed.script /etc/ssh/sshconfig

I've added a backup extension to the -i option. You're a braver man than I am if you edit major configuration files without making a backup copy first! (It's also necessary if you work on Mac OS X or BSD; the sed there requires an extension with -i.)

Upvotes: 11

devnull
devnull

Reputation: 123508

Since the patterns to be matched are similar, you could make use of alternation for the 4 strings and capture it. Make the # at the beginning of the string optional.

The following would combine those into one:

sed -i -r 's/^#?(PermitRootLogin|PermitEmptyPasswords|PasswordAuthentication|X11Forwarding) yes/\1 no/' /etc/ssh/sshd_config

If your version of sed doesn't support extended regular expressions, you could say:

sed -i 's/^#\{0,1\}\(PermitRootLogin\|PermitEmptyPasswords\|PasswordAuthentication\|X11Forwarding\) yes/\1 no/' /etc/ssh/sshd_config

Upvotes: 12

fedorqui
fedorqui

Reputation: 289735

You can use -e:

sudo sed -i -e 'first_command' -e 'second command' ... -e 'last command' /etc/ssh/sshd_config

Upvotes: 3

Related Questions