Herriman
Herriman

Reputation: 21

Use sed to change an entry of a configuration file

I want to change the following line in /etc/security/limits.conf from

#*               soft    core           0

to

*               soft    core            unlimited

to enable core dump.

I tried to use the following sed command but it did nothing:

sed -e "s/^\#\*\([ ]+soft[ ]+core\)[0-9][0-9]*$/\*\1 unlimited/" limits.conf

Where did I do wrong?

Upvotes: 0

Views: 677

Answers (2)

Jotne
Jotne

Reputation: 41446

This awk should do:

awk '/^#.*soft.*core/ {sub(/^#/,"");sub(/0$/,"unlimited")}1' file
*               soft    core           unlimited

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 753525

Mechanics of sed

There are a variety of issues:

  1. You don't need the backslash in front of the #, nor in front of the * in the replacement text. They don't do much harm, but they are not necessary.
  2. You need to allow for spaces between core and the number.
  3. You didn't allow for blanks and tabs in the file.
  4. You didn't allow for trailing white space on the line (which might not matter).
  5. You didn't explicitly enable extended regular expressions, and you did use the old-style \(…\) capturing notation, but that means + has no special meaning.
  6. You didn't modify the file in place with the -i option (which is fine while you're getting the sed command correct).

You should be able to use (GNU sed):

sed -r -e "s/^#\*([[:space:]]+soft[[:space:]]+core)[[:space:]]+[0-9][0-9]*[[:space:]]*$/\*\1 unlimited/" limits.conf

The [[:space:]] notation recognizes all sorts of white space (including newlines, etc); you could also use [[:blank:]] which only recognizes blanks and tabs if you prefer.

You could also use the old-style notation:

sed -e "s/^#\*\([[:space:]]\{1,\}soft[[:space:]]\{1,\}core\)[[:space:]]\{1,\}[0-9][0-9]*[[:space:]]*$/*\1 unlimited/" limits.conf

If you want to preserve the white space between core and the number, you can:

sed -e "s/^#\*\([[:space:]]\{1,\}soft[[:space:]]\{1,\}core[[:space:]]\{1,\}\)[0-9][0-9]*[[:space:]]*$/*\1unlimited/" limits.conf

The close for the capture is moved, and there's no need to add a space in the replacement string.

Be cautious when modifying the system file

Note that you should be very careful when you are sure your script is ready to modify the production file. I usually create a new file, check it, then copy the old file to a date/time-stamped file name, and copy the new file over the original. Alternatively, use a suffix with -i, probably with date/time again.

sed -i .$(date +'%Y%m%d.%H%M%S') -e "s/^#\*\([[:space:]]\{1,\}soft[[:space:]]\{1,\}core[[:space:]]\{1,\}\)[0-9][0-9]*[[:space:]]*$/*\1unlimited/" limits.conf

The advantage of that format (which is based on ISO 8601:2004) is that successive files sort into date order without any special sorting options. You can add punctuation into the date/time format if you wish.

Either way, if the new file gives problems, you've got (a copy of) the original which you can put back so that the system is running again smoothly as quickly as is reasonably feasible.

Upvotes: 5

Related Questions