8
\$\begingroup\$

I'm running a MediaWiki instance from a home server where the public IP address is not guaranteed to remain static. The following script is meant to run at boot time to check if the IP address has been changed an if so to update the relevant line in the LocalSettings.php file.

Here's the script:

#!/bin/bash

echo -n 'Retrieving public IP address... '
current_ip=` dig +short myip.opendns.com @resolver1.opendns.com `

if [ "$current_ip" == "" ]; then
    echo 'no response. No action taken.'; exit 1;
# check for a well formed IP adress: 000.000.000.000
elif [[ $current_ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
    echo $current_ip
else
    echo 'invalid IP address detected. No action taken'; exit 2;
fi

old_ip=`cat /var/lib/mediawiki/LocalSettings.php | grep '\$wgServer' | cut -d '"' -f2 | cut -d\/ -f3`
if [ "$old_ip" == "$current_ip" ]; then
    echo 'LocalSettings.php is already up-to-date. No action taken.'
else
    echo -n "Replacing $old_ip with $current_ip in LocalSettings.php... "
    sed -i.bak "s|\$wgServer =.*|\$wgServer = \"http://${current_ip}\";|" /var/lib/mediawiki/LocalSettings.php
    echo 'done.'
fi
\$\endgroup\$
6
\$\begingroup\$

Use $(...) always

There's really no good reason today to use `...`, always use the modern $(...) instead.

Avoid flags of echo

The flags of echo, such as -n don't work consistently in all systems, so it's better to avoid them when possible. If you really don't want to print a newline, you could use printf, though it's not POSIX compliant.

Checking that a variable is not empty

Instead of this:

if [ "$current_ip" == "" ]; then

You could write this:

if [ ! "$current_ip" ]; then

Also note that == is not a documented operator of the [ ... ] builtin, it's =.

Unnecessary semicolons

Semicolons at end of lines are unnecessary.

Unnecessary cat

The cat is unnecessary here, you could use the filename as argument of grep:

old_ip=`cat /var/lib/mediawiki/LocalSettings.php | grep '\$wgServer' | cut -d '"' -f2 | cut -d\/ -f3`

Unnecessary escape

In cut -d\/ -f3, no need to escape the /, it is not a special character that the shell would expand.

Finding fixed patterns with grep

In grep '\$wgServer' you correctly escaped the $ to suppress its special meaning in regular expressions. Another alternative is to tell grep that the pattern is a fixed string and not a regex, using the -F flag: grep -F '$wgServer'.

Single-quoting vs double-quoting

The sed could be a bit simpler by enclosing the command in single-quotes instead of double-quotes:

sed -i.bak 's|^\$wgServer =.*|$wgServer = "http://'"$current_ip"'"|' /var/lib/mediawiki/LocalSettings.php
\$\endgroup\$
  • \$\begingroup\$ In the last suggestion, are the double-quotes around '"$current_ip"' necessary? I've tried without them and it gives the same results. \$\endgroup\$ – afuna Jul 30 '17 at 21:16
  • \$\begingroup\$ @afuna It's a good habit to always double-quote variables. Otherwise, bad things could happen if the value is not exactly one word. \$\endgroup\$ – 200_success Jul 31 '17 at 4:57
  • 2
    \$\begingroup\$ @afuna strictly speaking the double-quotes are not necessary here, because the code before this line ensures that current_ip only contains digits and dots, which don't need escaping. But it's a good practice to double-quote all variables used on the command line. \$\endgroup\$ – janos Jul 31 '17 at 4:57
  • \$\begingroup\$ The printf utility is in POSIX. \$\endgroup\$ – Palec Jul 31 '17 at 11:44
  • \$\begingroup\$ Another alternative to [ ! "$current_ip" ] is [ -z "$current_ip" ]. See test. \$\endgroup\$ – Palec Jul 31 '17 at 11:48
7
\$\begingroup\$

That's nutty, trying to address a server by a changing IP address. Reconfiguring the wiki to adjust to it is even crazier.

The standard practice for adapting to dynamic IP addresses is to use a dynamic DNS service. Then, everything else works normally.

  1. Pick a hostname, like afuna.noip.com. Run a DDNS client to register your hostname whenever you acquire a DHCP lease, and re-register that hostname periodically thereafter.
  2. Use it to form the URL of your site, e.g. https://afuna.noip.com/.
  3. Configure your MediaWiki setting using that URL once, and you won't need that hacky script anymore.
\$\endgroup\$
  • 1
    \$\begingroup\$ Thanks for the advice. I've just begun learning Linux, and the script was more of a 'see if you can do it' than a permanent solution. The whole setup is mainly to cut my teeth on. \$\endgroup\$ – afuna Jul 30 '17 at 20:48
1
\$\begingroup\$

A more portable shebang would be #! /usr/bin/env bash, which tends to be of greater interest for other interpreters such as python.

Your "validate a dotted quad" logic seems more complex than necessary. Consider using set -e so the script bails out at first error, for example when =~ finds the IP is empty string. Equivalently, prepend a nonce character: _$current_ip =~ ^_[0-9]... The comment is a bit odd, it suggests that dig +short produces leading zeros when it does not. Your regex uses ^ and $ anchors, which is good practice.

Writing cut -d\/ -f3 seems weird, better to just say cut -d/ -f3 with no escaping.

Please edit your posting so it asks a question.

\$\endgroup\$

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.