Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I need to add:

user_xattr,acl,barrier=1

to my /etc/fstab file. Is there a way to do this via the via shell script?

I only want to edit the '/' mount.

Here is what I have before I manually edit it:

UUID=eb287d10-60a8-4a9a-9148-5f907fc7a8be / ext4 errors=remount-ro 0 1

Here is what it looks like after I manually add the lines:

UUID=eb287d10-60a8-4a9a-9148-5f907fc7a8be / ext4 user_xattr,acl,barrier=1,errors=remount-ro 0 1

I know that the sed -i command will not work here because it only adds lines...

Also script be run on multiple computers so it has to be able to "know" that the UUID will be different.

share|improve this question
    
You can use sed to replace, also would passing the UUID as a parameter to a command work ? –  NGRhodes Apr 4 at 14:19
    
If I am getting this right then you mean pasting in the UUID of the drive for the command? If so then this script is supposed to be automated. Here is a link:github.com/elliot-labs/Samba4-AD-DC-Auto-Setup –  Elliot Labs Apr 4 at 15:01
    
if you're managing a lab or cluster, check out ansible (ansible.com), to automate this sort of thing. –  ImaginaryRobots Apr 4 at 15:10
    
Thanks for the link. Not really yet and I don't have any budget this is more of a charity thing with support for future projects. –  Elliot Labs Apr 4 at 15:12

2 Answers 2

up vote 11 down vote accepted

Actually, sed could work perfectly well, but here are some more choices as well:

1. sed

sudo sed -i.old -r '/[ \t]\/[ \t]/{s/(ext4[\t ]*)([^\t ]*)/\1\2,user_xattr,acl,barrier=1/}' /etc/fstab

Explanation:

  • -i.old : Edit the file in place and create fstab.old as a backup of the original file before the changes.
  • -r : Enable extended regular expressions.
  • /[ \t]\/[ \t]/{} : If this line matches a / surrounded by a space or tab (if this line describes the / mountpoint).
  • s/(ext4[\t ]*)([^\t ]*)/\1\2,user_xattr,acl,barrier=1/ : s/pat/replacement/ is the substitution operator, it will replace pat with replacement. Here, we are matching ext4 and any following space or tab (needed to anchor the match, if your file systems are not ext4, you'll need to change that) and then capturing (that's what the parentheses do) the longest stretch of non-whitespace characters after that. In other words, capturing the options field of fstab. We then replace those with \1 (the first captured pattern), \2 (the 3nd capturef pattern, the original options) plus the extra options you wanted to add.

2. Perl

sudo perl -i.old -pane 's/$F[3]/$F[3],user_xattr,acl,barrier=1/ if $F[1] eq "/"' /etc/fstab

Explanation:

  • -i.old : Again, this will cause the file to be edited in place and a backup called fstab.old will be created.
  • -pane : -p means print each line, -a automatically splits input lines into fields on white space and saves them as the array @F. -n means read line by line and -e lets you pass a script on the command line.
  • The actual script will add the extra options to the current value of the 4th field ($F[3],1st field is $F[0]) only if the second ffield ($F[1], the mount point) is /.

3. awk

sudo cp /etc/fstab /etc/fstab.old && 
 awk '($2=="/"){$4=$4",user_xattr,acl,barrier=1"}1;' /etc/fstab.old | sudo tee /etc/fstab

Explanation:

Most versions of awk don't allow in place editing so the first command will create a backup copy. The awk will then check if the 2nd field is / and if so, will add the required text to the 4th field, the options. The 1; is awk shorthand for "print the line". The sudo tee is just a trick to allow printing to /etc/fstab since simple redirection won't work with sudo.

4. pure bash

sudo cp /etc/fstab /etc.fstab.old
while read fs mp ty op du pa; do 
    [[ $mp = "/" ]] && op="user_xattr,acl,barrier=1,""$op"; 
    printf "%s %s %s %s %s %s\n" "$fs" "$mp" "$ty" "$op" "$du" "$pa"; 
done < /etc/fstab.old | sudo tee /etc/fstab

Explanation

  • while read fs mp ty op du pa; do ...; done < /etc/fstab : Read each fstab line and split into the relevant fields.
  • [[ $mp = "/" ]] && op="user_xattr,acl,barrier=1,""$op"; if the mount point is /, add the extra options to $op.
  • The printf just prints each line correctly.
share|improve this answer
    
I want the UUID to be ignored because it will be different from computer to computer. Also thanks for this I will have to test it. NOTE: I am only using shell scripts and am not interested in using pearl or any other programming languages. (I am not sure if awk is one) –  Elliot Labs Apr 4 at 14:56
    
Also good Idea in making a backup file. I assume that I can change '.bak' to '.original' if I want... –  Elliot Labs Apr 4 at 14:58
    
@ElliotLabs all of these run in the shell, yes awk and perl are languages but here they are being run as shell commands, botho will be available on any *nix machine (there are some older, minimalist AIX that might not have one or the other but those are rare). Anyway, I added a pure bash option as well. And yes, I know you want the UUID to be ignored, that's why all my methods use a different approach to find the relevant line. –  terdon Apr 4 at 15:04
    
It works great! Thanks! –  Elliot Labs Apr 4 at 15:04
    
I just want it to be as compatible as possible because a minimal install might not have some of these commands. I understand that it is unlikely but I am doing this just for good measure... –  Elliot Labs Apr 4 at 15:05

sed -i is not used only to add lines as you said. It can be used in many other cases. And in your case like follow:

str="/[[:space:]]*ext4[[:space:]]*errors=remount-ro[[:space:]]*0[[:space:]]*1"
sed -i.bak "s#$str#/ ext4 user_xattr,acl,barrier=1,errors=remount-ro 0 1#" /etc/fstab

Like this $str which is equal with something like / ext4 errors=remount-r 0 1 (where each space can be any group of white spaces <tab> and <space>) will be replaced with / ext4 user_xattr,acl,barrier=1,errors=remount-ro 0 1 in /etc/fstab file.

The class [:space:] (which match the whitespace characters <tab> and <space>) is specified by POSIX, so you should have no problems in using it in any shell.

share|improve this answer
    
+1. You can use & in place of $str on the right-hand side. –  glenn jackman Apr 4 at 14:41
    
This won't work, the OP specified that the UUIDs will be different since this needs to be run on multiple machines. Also, this will fail if the fstab fields are separated by tabs or even multiple spaces. –  terdon Apr 4 at 14:45

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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