sed + append new lines after matched word but ignore if lines are exists - sed

we create the follwinmg sed line in order to add the lines after mached word ( on redhat 7.x machines )
sed -i '/\[Service\]/a MemoryAccounting=yes\nMemoryCurrent=8192000\nMemoryLimit=8192000' /lib/systemd/system/rsyslog.service
example of the file before update
cat /lib/systemd/system/rsyslog.service
[Unit]
Description=System Logging Service
;Requires=syslog.socket
Wants=network.target network-online.target
After=network.target network-online.target
Documentation=man:rsyslogd(8)
Documentation=http://www.rsyslog.com/doc/
[Service]
Type=notify
EnvironmentFile=-/etc/sysconfig/rsyslog
ExecStart=/usr/sbin/rsyslogd -n $SYSLOGD_OPTIONS
Restart=on-failure
UMask=0066
StandardOutput=null
Restart=on-failure
[Install]
WantedBy=multi-user.target
;Alias=syslog.service
example of the file after the update by sed
cat /lib/systemd/system/rsyslog.service
[Unit]
Description=System Logging Service
;Requires=syslog.socket
Wants=network.target network-online.target
After=network.target network-online.target
Documentation=man:rsyslogd(8)
Documentation=http://www.rsyslog.com/doc/
[Service]
MemoryAccounting=yes
MemoryCurrent=8192000
MemoryLimit=8192000
Type=notify
EnvironmentFile=-/etc/sysconfig/rsyslog
ExecStart=/usr/sbin/rsyslogd -n $SYSLOGD_OPTIONS
Restart=on-failure
UMask=0066
StandardOutput=null
Restart=on-failure
[Install]
WantedBy=multi-user.target
;Alias=syslog.service
now the problem is when we run again the sed line then we get duplicate lines as
[Service]
MemoryAccounting=yes
MemoryCurrent=8192000
MemoryLimit=8192000
MemoryAccounting=yes
MemoryCurrent=8192000
MemoryLimit=8192000
any suggestion how to ignore editing when the lines are already exists ?
notes:
in order to complete service update we need to do the following:
systemctl daemon-reload
systemctl restart rsyslog.service

This should work
sed -i.SAVED '/\[Service\]/N;
s/\n/ /;
/\[Service\] Type=notify/c\
[Service]\
MemoryAccounting=yes\
MemoryCurrent=8192000\
MemoryLimit=8192000\
Type=notify
/\[Service\] M.*/s/ /\n/
' /lib/systemd/system/rsyslog.service
it's joining lines using N, replacing the nl with space checking if it matches the original line.
Also saving the original file just in case.

Using sed
$ sed -Eei.bak '/\[service]/I{n;/^memoryaccounting/I!{i MemoryAccounting=yes\nMemoryCurrent=8192000\nMemoryLimit=8192000' -e '}}' input_file
[Unit]
Description=System Logging Service
;Requires=syslog.socket
Wants=network.target network-online.target
After=network.target network-online.target
Documentation=man:rsyslogd(8)
Documentation=http://www.rsyslog.com/doc/
[Service]
MemoryAccounting=yes
MemoryCurrent=8192000
MemoryLimit=8192000
Type=notify
EnvironmentFile=-/etc/sysconfig/rsyslog
ExecStart=/usr/sbin/rsyslogd -n $SYSLOGD_OPTIONS
Restart=on-failure
UMask=0066
StandardOutput=null
Restart=on-failure
[Install]
WantedBy=multi-user.target
;Alias=syslog.service

This sed command will skip the insertion of text if the [Service] is immediately followed by a line starting with MemoryAccounting=.
sed -i.orig '
/\[Service]/{
n
/^MemoryAccounting=/b
i\
MemoryAccounting=yes\
MemoryCurrent=8192000\
MemoryLimit=8192000
}' rsyslog.service

Related

using sed command need to change one line in nginx conf

Need to change one line in nginx.conf
client_max_body_size 1m to client_max_body_size 10m I used this command
sed -i "s/^client_max_body_size 1m;$/client_max_body_size 10m;/g" /etc/nginx/nginx.conf
sed: 1: "nginx.conf": extra characters at the end of n command
got this message... I don't know what I did wrong.
You can use
sed -i '' 's/^client_max_body_size 1m;$/client_max_body_size 10m;/g' /etc/nginx/nginx.conf
The '' after -i option in FreeBSD sed enable inplace matching.

Command substitution in fish

I'm trying to migrate this working command
docker-compose $(find docker-compose* | sed -e "s/^/-f /") up -d --remove-orphans
from bash to fish. The intention of this command is to get this
docker-compose -f docker-compose.backups.yml ... -f docker-compose.wiki.yml up -d --remove-orphans
My naive try
docker-compose (find docker-compose* | sed -e "s/^/-f /") up -d --remove-orphans
is not working, though. The error is:
ERROR: .FileNotFoundError: [Errno 2] No such file or directory: './ docker-compose.backups.yml'
What is the correct translation?
The difference in behavior is due to the fact fish, sanely, only splits the output of a command capture on line boundaries. Whereas POSIX shells like bash split it on whitespace by default. That is, POSIX shells split the output of $(...) on the value of $IFS which is space, tab, and newline by default.
There are several ways to rewrite that command so it works in fish. The one that requires the smallest change is to change the sed to insert a newline between the -f and the filename:
docker-compose (find docker-compose* | sed -e "s/^/-f\n/") up -d --remove-orphans

Modify /etc/sudoers with sed

I'm trying to write a sed program to append Defaults:user !requiretty after the line Defaults requiretty in /etc/sudoers. I tried the following command:
sudo sed -i '/Defaults requiretty/a Defaults:user !requiretty' /etc/sudoers
This is working properly, but only if there are 4 spaces between 'Defaults' and 'requiretty'. I want to modify it in order to work with any number of spaces, so I tried the following:
sudo sed -i '/Defaults\s+requiretty/a Defaults:user !requiretty' /etc/sudoers
I checked the pattern on regexr and it was okay, but still the command does not insert the required line. Why not?
try this;
sed '/Defaults.\s\s.requiretty/a Defaults:user !requiretty' /etc/sudoers
Working from Mustafa's answer, here's a way to do the same thing with some safety checks added
SUDOER_TMP=$(mktemp)
cat /etc/sudoers > $SUDOER_TMP
sed -i -e 's/PATTERN/OUTPUT/' $SUDOER_TMP
visudo -c -f $SUDOER_TMP && \ # this will fail if the syntax is incorrect
cat $SUDOER_TMP > /etc/sudoers
rm $SUDOER_TMP

sed: can't read /home/me/weather: No such file or directory

I have the following extract from a script that fetches weather information from accuweather:
wget -O ./weather_raw $address
if [[ -s ./weather_raw ]]; then
egrep 'Currently|Forecast<\/title>|_31x31.gif' ./weather_raw > ./weather
sed -i '/AccuWeather\|Currently in/d' ./weather
sed -i -e 's/^[ \t]*//g' -e 's/<title>\|<\/title>\|<description>\|<\/description>//g' ./weather
sed -i -e 's/<img src="/\n/g' ./weather
sed -i '/^$/d' ./weather
sed -i -e 's/_31x31.*$//g' -e 's/^.*\/icons\///g' ./weather
sed -i -e '1s/.$//' -e '3s/.$//' -e '6s/.$//' ./weather
for (( i=2; i<=8; i+=3 ))
do
im=$(sed -n ${i}p ./weather)
sed -i $i"s/^.*$/$(test_image $im)/" ./weather
done
fi
The command that triggers the code above is in a conkyrc file and its ~/.conkyblue/accu_weather/rss/acc_rss. When I run the conkyrc script from the prompt, I get an error
sed: can't read /home/me/weather: No such file or directory
And indeed when I check, the "weather" file is not created. However if run the command ~/.conkyblue/accu_weather/rss/acc_rss directly from the prompt, it works as expected and create and puts content into the /home/me/weather file.
I don't know anything about the sed command although I'm trying to learn it as a result of this bother.
What could be the problem with the code. I don't think its a permission issue since the folder its writing into is my home folder and I of-course own it.
Thanks
It should have been created by egrep.
When you run your script, the weather directory will be created in the pwd of the script process.
Check and see why egrep does not create the file, or in which directory it created it.

sed + add remark before string in specific line

My target is to add remark "#" before the "dialog" string
only in line that has the "Restart nfs and apply changes" line
Why my sed command not add the "#" char before the dialog string? , what wrong? In my syntax?
sed -i -r '/Restart nfs and apply changes/s/dialog ?$/#dialog/' /etc/init.d/nfsscript.sh
the line in /etc/init.d/nfsscript.sh file :
dialog --clear --colors --title "nfs Config" --yesno "Restart nfs and apply changes?" 10 20
This might work:
sed -e '/Restart nfs and apply changes/s/dialog/\#dialog/' -i /etc/init.d/nfsscript.sh