Solved Editing Config Files

I was wondering if there was a command that came standard with FreeBSD for editing configuration files much like sysrc(8) or sysctl(8) that work on other config files that follow the same parameter=value format. I'd like to ultimately modify other config files like /boot/loader.conf, /etc/jail.conf, etc. in the same or similar manor as /etc/sysctl.conf and /etc/rc.conf.

I was able to use sysrc(8) on /boot/loader.conf:
Bash:
# sysrc -f /boot/loader.conf loader_delay=2
loader_delay: 2 -> 2

However, whenever I try a parameter that has a namespace, sysrc(8) doesn't care for that too much:
Bash:
# sysrc -f /boot/loader.conf kern.vty=vt
sysrc: kern.vty: name contains characters not allowed in shell

Thanks in advance!
 
sysrc(8) is only for rc files. You shouldn't use it to manipulate other files e.g. /boot/loader.conf. Please don't do that.
Try this one. it will show you what is wrong with your approach:
sysrc -f /boot/loader.conf GIT=IS_BAD.
Now check the result in /boot/loader.conf (open in editor).
Before using sysrc(8) , dump a list of all configuration variables which it could access/change including defaults:
sysrc -A
Admins with large servers manage their stuffs including confs with programs like sysutils/puppet6. I never used such programs. Do your research.
 
There are many libraries (C, Perl, Python etc.pp.) to handle key=value syntax. The benefit of sysrc(8) is that it checks for duplicates & does some other limited checks like the one you ran into. You may want to search the web for some shell script (or scriptlets) library site. This would be my 1st attempt.
 
It's recommended to use sysrc(8) to edit rc.conf because it's safer and easier. The length of command, short or long is not an issue. There're different ways to add entry to rc.conf: editor, echo, .... sysrc(8) is one of them. I personally use cat(1) to append backed-up setting to config files, including rc.conf; and I use nvi(1) to edit them. There's going to be syntax error and/or mistakes. but that's on me.
 
...and using a tool like sysrc(8) can detect many of such human errors. If I got it right, the OP wants to find or write a more general tool, for safety & probably automation, which are two good reasons.
 
Thanks everyone for your responses!

the OP wants to find or write a more general tool, for safety & probably automation, which are two good reasons.

You are correct. I wanted to have both safety and automation. A consistent way to edit all, or most, config files with some high level syntax checks.

I have looked into sysutils/puppet6 and sysutils/ansible, but not textproc/augeas (yet).

I was hoping to find a solution that was part of FreeBSD's base system. And to answer my original question, there isn't one. But I think my options are either to write a script, or install a package. I'll do some more research on my options. Thanks again!
 
The reason I use augeas with Puppet is because you can only define a file resource once, either with a full config file or a template for a full config file. So if you have two modules that need to modify the same config file you have a problem. With augeas you can simply define what settings you want changed and leave the rest of the file as-is. Also useful if you need to allow people to edit configuration files but still want to make sure certain parameters have specific values. A regular file resource with Puppet would simply overwrite the user-made changes.
 
The reason I use augeas with Puppet is because you can only define a file resource once, either with a full config file or a template for a full config file. So if you have two modules that need to modify the same config file you have a problem. With augeas you can simply define what settings you want changed and leave the rest of the file as-is. Also useful if you need to allow people to edit configuration files but still want to make sure certain parameters have specific values. A regular file resource with Puppet would simply overwrite the user-made changes.

Just tried it. Unforunately augeas (augtool print) doesn't recognize the format of /etc/pkg/FreeBSD.conf or /etc/freebsd-update.conf or /usr/local/etc/tarsnap.conf and probably many others, which limits its usefulness in our case.
 
I think such a tool to edit /boot/loader.conf would be useful in the base system and should probably be included. My philosophy around that is, if there is a file format that the base system uses, then it's got the tooling to parse it programmatically in it's native format. Therefore there should also exist tooling to safely edit it programmatically in it's native format, in addition to being able to edit it via a text editor.

Anyway... here's a small shell function that I put together (I think I stole some parts of it from another script a long time ago).

It lets you edit using the same syntax as sysrc. Except it doesn't do all the fancy stuff the sysrc is capable of.

Code:
setconfig () {
    while getopts :f: flag; do
        case "$flag" in
        f) sc_config=$OPTARG ;;
        \?) echo "Invalid option: -$OPTARG" >&2; return 1 ;;
        :) echo "Option -$OPTARG requires an argument." >&2; return 1 ;;
        esac
    done
    shift $(($OPTIND-1))

    sc_value=$1
    sc_directive=`echo $sc_value | cut -d'=' -f1`

    if [ -z "$sc_value" ] || [ -z "$sc_directive" ] || [ -z "$sc_config" ]; then echo -e \\n"Mssing arguments"; return 1; fi

    if grep -sq $sc_directive $sc_config >&2; then
        sed -i '' -e "s#$sc_directive.*#$sc_value#" $sc_config
    else
        echo $sc_value >> $sc_config
    fi
}

Here's one for INI files. It's not perfect either, but it's gotten the job done.

Code:
iniconfig () {
    while getopts :f:s: flag; do
        case "$flag" in
        f) ini_config=$OPTARG ;;
        s) ini_section=$OPTARG ;;
        \?) echo "Invalid option: -$OPTARG" >&2; return 1 ;;
        :) echo "Option -$OPTARG requires an argument." >&2; return 1 ;;
        esac
    done
    shift $(($OPTIND-1))

    ini_value=$1
    ini_directive=`echo $ini_value | cut -d'=' -f1`

    if [ -z "$ini_value" ] || [ -z "$ini_section" ] || [ -z "$ini_directive" ] || [ -z "$ini_config" ]; then    echo -e \\n"Mssing arguments"; return 1; fi

    # Keep track of the end of file line
    last_line=$(awk 'END {print NR}' $ini_config)

    # Find out what line the section begins
    starting_line=$(awk "/\[${ini_section}\]/ {print FNR}" $ini_config)

    # If the section does not exists
    if [ -z "$starting_line" ]; then
        # Add this section
        starting_line=$last_line
        echo -e "[${ini_section}]" >> $ini_config;
    fi

    # Find out what line the section ends
    next_section=$(awk "NR>${starting_line}&&/\[.*\]/ {print FNR}" $ini_config)
    if [ -z "$next_section" ]; then
        ending_line=$last_line
    else
        ending_line=$(($next_section - 1))
    fi

    # Make the change within the disired range
    # Search starts right after the section header, not including it.
    starting_line=$(($starting_line + 1))
    if awk "NR==${starting_line},NR==${ending_line}" $ini_config | grep -sq $ini_directive >&2; then
        sed -i '' -e "${starting_line},${ending_line}s#$ini_directive.*#$ini_value#" $ini_config
    else
        insert_line=$ending_line
        # If we are at EOF, add a new line
        if [ $insert_line == $last_line ]; then echo >> $ini_config; fi
        before_line=$(( $ending_line - 1))
        before_line_value=$(awk "NR==${before_line}" $ini_config)
        if [ -z "$before_line_value" ]; then insert_line=$before_line; fi
        insert_line_value=$(awk "NR==${insert_line}" $ini_config)
        if [ ! -z "$insert_line_value" ]; then insert_line=$(($insert_line + 1)); fi
        #echo -e "${insert_line}\ni\n${ini_value}\n.\n\$\na\n\n.\n?^..*?+1,.d\nw\n" | ed -s $ini_config
        echo -e "${insert_line}\ni\n${ini_value}\n.\nw\n" | ed -s $ini_config
    fi
}


Just tried it. Unforunately augeas (augtool print) doesn't recognize the format of /etc/pkg/FreeBSD.conf or /etc/freebsd-update.conf or /usr/local/etc/tarsnap.conf and probably many others, which limits its usefulness in our case.
I think those files are in UCL format, I could be wrong.
 
Back
Top