5
\$\begingroup\$

As I am new to bash scripting, and want to use apt-get in my university. I know that many people have issues when trying to do so. My focus is simplicity and ease of use, but still need to be somewhat robust.

#!/bin/bash 
string="install"
errormsg="\n\tInvalid input\n You should run this script with the following structure:\n\n sudo apt-proxy-install.sh install USERNAME PASSWORD\n\n "
DIRECTORY=~/bin/
if [ "1ドル" = "$string" ] && { ! ([ -z "3ドル" ] || [ -z "3ドル" ]) }
 then 
 if [ ! -d "$DIRECTORY" ]; then
 mkdir ~/bin/
 fi
 printf "#!/bin/bash\nhttp_proxy=""http://2ドル:[email protected]:3128"" sudo apt-get \${@:2}" > ~/bin/apt-proxy
 chmod 777 ~/bin/apt-proxy
 PATH=~/bin:$PATH
 addpath="export $PATH"
 sudo cat ~/.bashrc $addpath > ~/.bashrc
 else
 printf "$errormsg"
fi

My question is: is this code acceptable, or should I improve it? If the answer is not, then please give me some hints.

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Dec 9, 2013 at 19:18
\$\endgroup\$
1
  • \$\begingroup\$ Assuming that apt-get should always use the HTTP proxy, configure /etc/apt/apt.conf with Acquire::http::Proxy "http://username:[email protected]:3128". You might consider the risk of storing a plaintext password to be acceptable if apt.conf is readable only by root. \$\endgroup\$ Commented Dec 9, 2013 at 20:52

4 Answers 4

3
\$\begingroup\$

Storing passwords in text files is never a good idea, especially if you give that file world-readable permissions.

Try this:

#!/bin/bash 
mkdir -p ~/bin/
# add ~/bin to PATH if not already there
echo '[[ :"$PATH": == *:"$HOME/bin":* ]] || PATH="$HOME/bin:$PATH"' >> .bashrc
# create the apt-proxy script
cat <<'END_SCRIPT' > ~/bin/apt-proxy
#!/bin/bash
stty -echo
printf "Password for %s: " "$LOGNAME"
read password
stty echo
echo
export http_proxy="http://${LOGNAME}:${password}@10.20.10.50:3128"
sudo -S apt-get "$@" <<< "$password"
END_SCRIPT
chmod 755 ~/bin/apt-proxy
cat <<INSTRUCTIONS
The apt-proxy script has been installed. 
You may need to log out and log back in before you can use it.
usage: apt-proxy package ...
INSTRUCTIONS
  • mkdir -p dir will silently do nothing if the directory already exists
  • you only need to add the user's bin dir to the PATH if it is not already there
  • DO NOT store the user's password. Have the user enter it each time.
  • you should not even need to use sudo to edit files in your home directory.
  • 777 permissions is overly generous: the world does not have to be able to edit the file
  • use sudo -S and pass the user's password via stdin
answered Dec 9, 2013 at 20:42
\$\endgroup\$
1
  • \$\begingroup\$ Additionally, you almost always want to quote "$@" to expand the command line arguments robustly. \$\endgroup\$ Commented Dec 9, 2013 at 23:22
1
\$\begingroup\$

NO!

Storing plaintext passwords in a world-readable file is not acceptable.

Making an executable file world-writable is not acceptable.

Asking for a password to be entered as a command-line parameter, where it would likely end up in ~/.bash_history, is not acceptable. The password would also be temporarily be visible to all users via /bin/ps, which is also bad practice.

answered Dec 9, 2013 at 20:39
\$\endgroup\$
1
\$\begingroup\$

This line has readability problems:

if [ "1ドル" = "$string" ] && { ! ([ -z "3ドル" ] || [ -z "3ドル" ]) }

You put 3ドル twice; I assume you meant 2ドル for one of them.

Since "$string" is just install, you might as well say install instead.

The compound conditional is hard to understand. Apply De Morgan's laws to obtain

if [ "1ドル" = install ] && ! [ -z "2ドル" ] && ! [ -z "3ドル" ]

... which is just

if [ "1ドル" = install ] && [ -n "2ドル" ] && [ -n "3ドル" ]

I would introduce explaining variables

command="1ドル"
username="2ドル"
password="3ドル"
if [ "$command" = install ] && [ -n "$username" ] && [ -n "$password" ]
answered Dec 10, 2013 at 0:01
\$\endgroup\$
0
\$\begingroup\$

This line...

sudo cat ~/.bashrc $addpath > ~/.bashrc

... is actually extremely problematic.

You will almost certainly wipe out the existing contents of ~/.bashrc: the shell will likely truncate ~/.bashrc before it runs sudo, and sudo runs cat, and cat reads the file. See Unix Big Redirection Mistake #1. The way to append to a file is using echo "$blah" >> ~/.bashrc.

The $addpath variable is incorrectly defined as addpath="export $PATH". You would be trying to export a variable named ~/bin:/bin:/usr/bin because there is no PATH=... assignment. You meant addpath="export PATH=\"$PATH\"".

Furthermore, cat $addpath has two errors: it's the wrong command (you want echo), and you failed to double-quote its argument. Therefore, it will just try to read files named export and PATH=~/bin:... — if you're lucky. If you're unlucky, $PATH could expand to a string that contains a nasty shell command. That scenario is admittedly farfetched, but that kind of carelessness in quoting is how exploits get introduced. When writing shell scripts, double-quote every variable you use unless you have a good reason not to.

sudo is unnecessary for that operation; it could even backfire if the sudoers doesn't allow cat to be executed. By the way, sudo would only elevate the cat ~/.bashrc to root privileges; the writing would still be done using output redirection in the non-elevated context.

~/.bashrc is not a good place to put a statement to edit $PATH, since it gets executed with every interactive shell. If you run bash from within Bash, the subshell would unexpectedly have its $PATH redefined. A more appropriate place might be ~/.bash_profile.

After correcting for the mistakes above, with the code

PATH="~/bin:$PATH"
addpath="export PATH=\"$PATH\""
echo "$PATH" >> ~/.bash_profile

... you would be "freezing" the current value of $PATH into ~/.bash_profile. Instead, you probably want to prepend ~/bin to whatever $PATH exists when ~/.bash_profile is executed in the future (notice the single quotes instead of double quotes):

echo 'export PATH=~/bin:$PATH' >> ~/.bash_profile
answered Dec 9, 2013 at 23:50
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.