2

I wish to create an executable bash script that will run the following commands as root, that is, using sudo su

iptables-save | awk '/^[*]/ { print $1 } 
                     /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; }
                     /COMMIT/ { print $0; }' | iptables-restore

My first attempt at bash scripting is as follows:

#!/bin/bash
sudo su
iptables-save | awk '/^[*]/ { print $1 } 
                     /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; }
                     /COMMIT/ { print $0; }' | iptables-restore
sleep 3;
exit 0

Could someone correct the above and make it workable?

6
  • 1
    First of all, don't use sudo to run su! You can use sudo -i for sudo su - or sudo -s for sudo su Commented May 25, 2014 at 19:30
  • @Artur Szymczak What is the difference between sudo -i and sudo -s in plain English? I have read the man pages and am still clueless. (I do not have a technical or IT background.) The man pages do not provide examples of instances where one might use sudo -i over sudo -s
    – user66229
    Commented May 25, 2014 at 22:45
  • 1
    sudo -i gives you login shell. It means, that shell configuration files, like /etc/profile are applied - you get shell, similar to the one, when you directly login on given user. sudo -s don't do this, giving you non-login shell - like su - just switch user. Commented May 26, 2014 at 12:58
  • @Artur Szymczak Thanks for the explanation. Just to make sure I understand it, when I wish to edit or make changes to files in, for example, /etc/default/grub or /dev/snd, I must use sudo -i. Can you provide an example in which I have to use sudo -s?
    – user66229
    Commented May 26, 2014 at 16:51
  • 1
    You could edit any files using sudo -s and sudo -i. The problem is related to environment variables, like PATH. In some distributions, you couldn't see some commands, because they are in /sbin dir, and PATH for normal user, doesn't include it. THe same problem is with DISPLAY, when you would like to run GUI command. Commented May 27, 2014 at 9:25

1 Answer 1

3

Shell scripts aren't quite the same as typing at a terminal.
What's going to happen here is that iptables-save is going to wait for sudo su to complete, and then run. What you want is to run iptables-save inside the sudo.

Secondly, sudo su is among the ranks of 'useless use of' examples. The proper equivalent is
sudo -i.

There are 2 approaches you can take to solving this.

Method 1

sudo -i <<'EOF'
iptables-save | awk '/^[*]/ { print $1 } 
                 /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; }
                 /COMMIT/ { print $0; }' | iptables-restore
EOF

This basically launches a root shell and sends that command through the shell.
The reason we don't don't just add a sudo in front of both the iptables-save and iptables-restore commands is that it will launch 2 sudos at the same time. This does not work well if they both end up trying to prompt for the password.
So this solution works around the issue by only launching a single sudo.

One line
As requested in your comment, you can do this in a single line, but it becomes much harder to read.

sudo -i sh -c 'iptables-save | awk '\''/^[*]/ { print $1 }; /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; }; /COMMIT/ { print $0; }'\'' | iptables-restore'

 

Method 2

sudo -v
sudo -n iptables-save | awk '/^[*]/ { print $1 } 
             /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; }
             /COMMIT/ { print $0; }' | sudo -n iptables-restore

This solution runs sudo the first time, without any command, simply a -v. This causes sudo to prompt for your password if your session is expired. Then any commands run within that session expiration window won't require a password. So launching 2 sudos at the same time is no longer an issue as neither of them will prompt (we add -n to make absolutely sure of this. It'll throw an error if it tries).

6
  • The first example is definitely best - the second only works if sudo is configured to store credentials for a length of time - which is, admittedly, extremely likely.
    – mikeserv
    Commented May 25, 2014 at 8:15
  • @Patrick: Thanks for the detailed explanation, even though I only understood about 50% of what you wrote. I have a question: Could you transform the 3 lines of the code into a single line? (The code that starts with iptables-save | awk '/^[*]/ { print $1 })
    – user66229
    Commented May 25, 2014 at 17:06
  • @Patrick: Could you also answer Question 2 please? I have edited my original post to include Question 2. Thanks in advance.
    – user66229
    Commented May 25, 2014 at 17:19
  • @user66229 You should ask that as another question. It's entirely unrelated to the original.
    – phemmer
    Commented May 25, 2014 at 17:59
  • @Patrick As advised, I have created a new question referenced by the following link: unix.stackexchange.com/questions/131937/…. But would it be possible for you to answer my question regarding how to combine the 3 lines of code into a single one? Or is that a totally new question?
    – user66229
    Commented May 25, 2014 at 18:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .