I am trying to write a script to edit systemd files.

On the CLI I can use the command:

sudo systemctl edit test.service

That opens a text editor, I make the changes and save no problems.

In a bash script I am trying to use the command:

sudo cat > /etc/systemd/system/test.service.d/override.conf <<EOF
ExecStartPre=/sbin/iw dev wlan0 interface add ap0 type __ap

It doesn't work because I don't have the right permissions.

I can then run the command:

sudo touch /etc/systemd/system/test.service.d/override.conf

and that works.

If I then run again:

sudo cat > /etc/systemd/system/test.service.d/override.conf <<EOF
ExecStartPre=/sbin/iw dev wlan0 interface add ap0 type __ap

It also fails on permissions.

As far as I can see, this seems to be an issue with the:

sudo cat > somefile << EOF
some file text

command sequence. sudo should break through any permission issues, but doesn't in this case.

Is there a solution??


This question is not really Pi specific, but there is a solution; viz do all your work on a temporary file. Following is an example I have used.

# script to customise ssmtp
# 2017-08-12

# copy sed script to a temporary file
cat << EOF > /tmp/sedscr
/^\s*index/s/index/index index.php/
/^\s*location \//,/^\s*}/ {
/^\s*location \//,/^\s*}/s/ =404/ \/index.php\?\$args =404/
/location ~ \\\\.php/i\\
    # insert from Derek Molloy. “Exploring Raspberry Pi.”\\
    location ~ \\\.php$ {\\
       fastcgi_pass unix:/var/run/php5-fpm.sock;\\
       fastcgi_index index.php;\\
       include fastcgi_params;\\
       fastcgi_param SCRIPT_FILENAME \$document_root/\$fastcgi_script_name;\\



# Check/create Backup Config File
if [ ! -e $CONFIG_FILE.orig ]; then
    sudo cp $CONFIG_FILE $CONFIG_FILE.orig

sed -f /tmp/sedscr $CONFIG_FILE >/tmp/nginx_sites
# sed -f /tmp/sedscr $CONFIG_FILE

# copy modified files from /tmp
sudo cp /tmp/nginx_sites $CONFIG_FILE
| improve this answer | |
  • I haven't seen that approach in any other answers but it looks like a good option. I can create the file I want in the ~ dir and then sudo mv it to where it needs to be. – dazz Sep 30 '18 at 8:52
  • That does mean I need to chown and chmod the final file but the code is easy to read. – dazz Sep 30 '18 at 9:00
  • @dazz it is difficult to generalise. Every time I modify a system file I make a backup (which is good practice) and it is much easier to test/verify on a copy, but what you have to do after depends on the files. The example I posted was one of a set of scripts I developed to configure a fresh install to my preferred settings - useful when going from Jessie to Stretch. This is not that uncommon - the book by Derek Molloy mentioned has similar examples. Unfortunately developing/testing these scripts can be time consuming and sed does take quite a bit of learning. – Milliways Sep 30 '18 at 11:34

OK I found this answer:

All redirections (including >) are applied before executing the actual command. In other words, your shell first tries to open /etc/php5/apache2/php.ini for writing using your account, then runs a completely useless sudo cat.

here: Redirection


Based on @Milliways answer, I have applied the following to a script I have written. This code creates a file in the home folder, then moves it to the required folder. Ownership and permissions are set to suit.

#Create the file in the home dir
cat > ~/12-ap0.network <<EOF
#move it to where it needs to be
sudo mv ~/12-ap0.network /etc/systemd/network/12-ap0.network
#set the ownership and permissions
sudo chown root:root /etc/systemd/network/12-ap0.network
sudo chmod 777 /etc/systemd/network/12-ap0.network

This adds just one extra line (mv ...) to the code.

| improve this answer | |

To be clear you should write the solution into your answer instead of linking to it:

rpi ~$ sudo bash -c 'cat > /etc/systemd/system/test.service.d/override.conf <<EOF
ExecStartPre=/sbin/iw dev wlan0 interface add ap0 type __ap

Consider the two ' character. Because of formating I couldn't put this in a comment.

| improve this answer | |

This happens because redirections are not handled by the command (sudo cat in your case), but by the shell running your script. Since the shell is not being run as root, it doesn't have the permissions to open the file.

A typical workaround is

sudo tee /etc/systemd/system/test.service.d/override.conf > /dev/null <<EOF
your text

The difference is that tee doesn't rely on redirections but actually opens the file by name.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.