Best Practice Advice - Install script and config variables

Allan

Member

Reaction score: 1
Messages: 37

I'm attempting to script (bash) the post installation settings of FreeBSD.

I'm trying to programmatically write the settings to /etc/rc.conf, /boot/loader.conf, /etc/sysctl.conf, /etc/devfs.conf, etc. just to name a few. I'm even trying to programmatically create .profile and other skeleton files. Currently, I'm storing my values to be written in arrays, but as I build out these arrays, I'm finding that I have (right now) 12 arrays with a couple having at least 25 elements all in the bash script file.

Is there a better way to do this?

Is there a way to store settings for an install type that can be parsed as needed that's more efficient than arrays in a script? Any best practice advice anyone has on this topic is much appreciated.
 
Last edited by a moderator:

unitrunker

Aspiring Daemon

Reaction score: 240
Messages: 537

Don't use bash for your post-install script. bash isn't part of base. Use sh(1). It's not that far from bash anyways and is far more portable.

If you must use bash - be sure to use the correct shebang.
Code:
#!/bin/env bash
and not
Code:
#!/bin/bash
Thinking out loud - could some of the skeleton files be done as "here is" documents?

 
Last edited by a moderator:

unitrunker

Aspiring Daemon

Reaction score: 240
Messages: 537

I forgot to add ...

sysrc(8) might be an easier way to edit the system configs from a script.
 
Last edited by a moderator:
OP
Allan

Allan

Member

Reaction score: 1
Messages: 37

Don't use bash for your post-install script. bash isn't part of base. Use sh(1). It's not that far from bash anyways and is far more portable.

If you must use bash - be sure to use the correct shebang.

That was part of my conundrum. I'm using bash because I needed to use arrays which isn't found in sh. I have my script broken into two parts: a pre-install script that runs entirely in sh. It checks for the existance of bash and if it doesn't exist, it installs it. It writes a temp file that after reboot if that file exists, it continues with the second script in bash.


sysrc(8) might be an easier way to edit the system configs from a script.

I'm going to look into this tonight!
 

ralphbsz

Son of Beastie

Reaction score: 2,181
Messages: 3,133

I think you are using bash way out of its comfort zone. Shells are designed primarily for interactive use, and their scripts intended for "short" tasks. If you are doing something complex (for example, which requires arrays), you should probably use different tools.

Note I'm not saying what other tool you should use. Personally, I would go with Python, or awk, or a preprocessing language like m4, but to each their own.
 

tommiie

Well-Known Member

Reaction score: 83
Messages: 297

I agree that if you need to install a different tool (in your case bash) you are better off installing e.g. Python instead which gives you the added bonus of being able to use Ansible, just to give an example.

I'm curious about awk(1) or m4(1) as I would not have considered awk(1) suitable for this task and I've never even heard of m4(1).
 
OP
Allan

Allan

Member

Reaction score: 1
Messages: 37

My bash script is actually fairly small. There are simple functions that edits config files, installs fonts, installs packages, etc. There's really not much too it logically. A majority now is array declarations/assignments because there are just so many config items to store.

However, I want to get this back on track...I'm not looking to implement a new language like Python or Perl because I'll be right back in the same boat: what is the best practice for handling config values? Because, I'm facing the exact same dilemma of them being in separate files or array values so switching to another language doesn't solve my problem.
 

tommiie

Well-Known Member

Reaction score: 83
Messages: 297

Could you share a code snippet so we can have a better idea of what you are currently doing?
 
OP
Allan

Allan

Member

Reaction score: 1
Messages: 37

Here's a small piece of code that writes values to the different files:

Bash:
printArrValues() {
# Parses through property array(s) and writes config files
# takes two values:
#  array of properties
#  filename to write
    declare -a argArray=("${!1}")
    echo $2
  for i in "${argArray[@]}"
do
    local str=$( echo ${i} | cut -d '=' -f1 )
    if ! grep ${str} $_file
    then
      if [ ${str:0:1} = "#" ]   # If it's a comment add a blank line
      then
          echo >> $_file
      fi
      echo  $i >> $_file
    else
        #if the line already exists, rewite it
        # 1) check if is a coment, then ignore
        # 2) rewrite the line as a comment
        # 3) add new line
        echo 'nothing here.'
    fi
done
}

setValues() {
# Function that parses through all of the values that needs to be set
# takes one value:
#  - Platform (svr=server, dsk=desktop)

platform=${1}


# Assign proper arrays depending on platform
case ${platform} in

  dsk) sysctl_props=("${sysctl_props_dsk[@]}")
       loader_props=("${loader_props_dsk[@]}")
       rc_props=("${rc_props_dsk[@]}")
       devfs_props=("${devfs_props_dsk[@]}")
       ;;
  svr)
       sysctl_props=("${sysctl_props_svr[@]}")
       loader_props=("${loader_props_svr[@]}")
       rc_props=("${rc_props_svr[@]}")
       devfs_props=("${devfs_props_svr[@]}")
       ;;
    *) echo 'No platform specified.  Making no changes.'
       ;;
esac


fnames=("/etc/sysctl.conf" "/boot/loader.conf" "/etc/rc.conf" "/etc/devfs.conf")

for file in "${fnames[@]}"
do
  printArrValues props_all[@] ${file}
done

}

And, here is just a sampling of how I use arrays to hold the config values:

Bash:
# /etc/rc.conf Properties
# rc_props_all+=( '' );

rc_props_all+=( '# Synchronize system time' );
rc_props_all+=( 'ntpd_enable="YES"' );
rc_props_all+=( '# Let ntpd make time jumps larger than 1000sec' );
rc_props_all+=( 'ntpd_flags="-g"' );
rc_props_all+=( '# Remote logins' );
rc_props_all+=( 'sshd_enable="YES"' );
rc_props_all+=( '# Auto Update MOTD' );
rc_props_all+=( 'update_motd="YES"');

Please keep in mind that this is a work in progress so there's some unfinished code. I'm not having any issues with the code, it's the logic of whether to use arrays in this manner (which are getting huge) or find a different way to attack this.
 

unitrunker

Aspiring Daemon

Reaction score: 240
Messages: 537

You could have one file or function that uses sysrc to set the "dsk" profile, another for "srv" profile and a menu to choose between the two.
 

tommiie

Well-Known Member

Reaction score: 83
Messages: 297

I would look at Ansible and jinja2 template files. I'm not sure it will be able to solve everything you're trying to do, but perhaps most of it and you will only need a few small scripts or better yet, only a few commands to be sent with Ansible (e.g. Ansible has a module that can restart services etc).
 
OP
Allan

Allan

Member

Reaction score: 1
Messages: 37

there's a whole raft of configuration management tools like puppet and chef which you are re-inventing.
I would look at Ansible and jinja2 template files.


I do appreciate the product recommendations - they're now on the list to evaluate. However, and I'm kicking myself for being remiss and not stating this earlier:

I'm taking this approach to better learn FreeBSD and to sharpen my scripting skills.

I have no doubt that the recommend products would speed me through this, but this is more of a personal self teaching project.
 

Mjölnir

Daemon

Reaction score: 1,507
Messages: 2,114

I have a conversation on that very same topic and I'd like you to join. Maybe I should start a new thread on that? I see the need and that 1000's of people are doing very similar tasks after/during each installation. This should be automated, and colaborated. Let's come together and join our forces!
It is here: FreeBSD CE (Community Edition), or you go into my user profile.
 

Mjölnir

Daemon

Reaction score: 1,507
Messages: 2,114

and do not use bash(1), instead use a portable sh(1) syntax. Added benefit: it can be used w/o any ports to be installed. This is another task you script might want to do, right?
 
Top