2

I am trying to create a auto install script since I have to do this installation task on multiple servers.

I have setup all the bind9 configuration files with my variables and thought it would have worked if the variables were set, however when the bind service starts, it errors out stating the variables aren't recognized.

For example of one of the errors showing up in /var/log/syslog:

dns_rdata_fromtext: /etc/bind/db.override:16: near ''$IP'': bad dotted quad

my configuration file:

;The Variables here are NIC and IP
; BIND data file for overridden IPs
;
$TTL  86400
@   IN  SOA ns1 root (
            2012100401  ; serial
            604800      ; refresh 1w
            86400       ; retry 1d
            2419200     ; expiry 4w
            86400       ; minimum TTL 1d
            )

; need atleast a nameserver
    IN  NS  ns1
; specify nameserver IP address
ns1 IN  A   $IP                ; external IP from $NIC
; provide IP address for domain itself
@   IN  A   $IP                ; external IP from $NIC
; resolve everything with the same IP address as ns1
*   IN  A   $IP                 ; external IP from $NIC

I have searched around the net and can't quite find a solution that reflects what I'm trying to do here. I'm not a shell scripting pro and have noticed bind and another program I am implementing variables into both can't seem to process variables when they're included in config files like I have done above.

  • Where's $IP getting set? – slm Sep 24 '14 at 0:49
  • I set $IP outside of the config. I have multiple configs that will be referencing $IP from the global environment. I've never setup config files in linux before where they reference an outside variable. If I echo $IP it will show me the content inside $IP however since I got the environment variable working. I'm not sure if the BIND program or other programs that I have the $IP variable inside of, can read variables like a bash script does? – RCG Sep 24 '14 at 1:22
1

You cannot do what you're trying to do here with Bind configuration files. The variable $IP cannot be set as a environment variable.

Typically what's done for a situation like this is you'll use either a script or a templating engine which can expand these variables (they're technically called macros, a lot of the time), where the templating engine will expand the files out while they're being deployed.

One that I'm more familiar with is called Cheetah. It's used by a provisioning system that I used to use for deploying systems, called Cobbler. There are many of these systems, such as Puppet, Chef, cfengine, Salt, etc.

Example of Cheetah template

Here's a very simple example that illustrates some of Cheetah's basic syntax.

Source: http://www.cheetahtemplate.org/examples.html

  <html>
    <head><title>$title</title></head>
    <body>
      <table>
        #for $client in $clients
        <tr>
          <td>$client.surname, $client.firstname</td>
          <td><a href="mailto:$client.email">$client.email</a></td>
        </tr>
        #end for
      </table>
    </body>
  </html>

Here the macros $client.email, $client.firstname, and $title will be expanded by Cheetah with actual values at run time. These engines are fairly capable, even giving you the ability to perform for loops, such as with the $client above.

But if your needs are meager I would cobble together a shell script to expand these $IP macros out at deployment time. You can use sed or bash to construct such a script that wouldn't be overly difficult to make.

You'll ultimately be playing this type of game:

Example

$ IP=1.2.3.4
$ sed -i "s/\$IP/$IP/g" sample.conf 

$ cat sample.conf
;The Variables here are NIC and IP
; BIND data file for overridden IPs
;
$TTL  86400
@   IN  SOA ns1 root (
            2012100401  ; serial
            604800      ; refresh 1w
            86400       ; retry 1d
            2419200     ; expiry 4w
            86400       ; minimum TTL 1d
            )

; need atleast a nameserver
    IN  NS  ns1
; specify nameserver IP address
ns1 IN  A   1.2.3.4                ; external IP from $NIC
; provide IP address for domain itself
@   IN  A   1.2.3.4                ; external IP from $NIC
; resolve everything with the same IP address as ns1
*   IN  A   1.2.3.4                 ; external IP from $NIC
  • Is there a better way to replace your variable in multiple files at once? If you have /location1/1.conf /location2/2.conf /location3/3.conf and they all have the $IP variable inside of them. Something that just allows me to run it all on one line vs having to write a new sed command that references each file to find and replace $IP. much like something along the lines of: sed -i "s/\$IP/$IP/g" /location1/1.conf /location2/2.conf /location3/3.conf or do I have to do sed -i "s/\$IP/$IP/g" /location1/1.conf && sed -i "s/\$IP/$IP/g" /location2/2.conf && sed -i "s/\$IP/$IP/g" /location3/3.conf? – RCG Sep 24 '14 at 2:28
  • @RyanGrant - I would use a array in Bash that contains the names of the files and do a for loop calling sed against each of the files. – slm Sep 24 '14 at 2:36
  • You could use find for that, e.g. find /path/to/files/ -name \*.conf -exec sed 's/.../g' {} \; to replace all files ending in .conf at the given location, searching within subdirectories. – Malvineous Jan 29 '17 at 9:11

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.