Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Cmd line parameters, env variables or config files?
1 point by gtirloni on Feb 6, 2019 | hide | past | favorite | 5 comments
What do you prefer and why?



I think that this is a false opposition thing: they're all good, and you should have all of them.

Command-line parameters, especially single character ones, are a quick and easy way to request ad hoc changes of program behavior. They're also common across many utilities, so you can expect that -d to display debugging output, and -h to be a hostname, -p to be a port number, -n to do a dry-run, etc.

Configuration files are good for persistent, per-program settings. If you always want altered behavior, a configuration file is easier than constantly adding command-line options. Note that this implies that command-line options should override configuration file options, and that a --no-foo variant can be useful.

Environment variables are good for long-term, multi-program configurations: EDITOR, DISPLAY, LANG, PAGER, TERM, etc. It can be good to have these available as command-line options (eg. -display, for Xt-based apps), but generally it's ok to override them with env FOO=bar program. Also of note: container orchestration systems are generally able to set environment variables, but might not be able to create (and later remove) a configuration file.

So ... it's often not the case that every program option should have all three means of control, but most programs should use all three mechanisms, depending on what type of optional behavior is being controlled.


> Environment variables are good for long-term, multi-program configurations

Not just that. They're also useful for when a program is called by another program and you want to control something about its invocation without having to modify the source code of that other program each time.

For example, I might use a different value for LESS when calling man than when calling git.


In order of preference:

1) Command line parameters, particularly when an application is using getopt() or getopt_long(). Among other things, they make it easier to test and debug an application. For example, daemonization and sandboxing should be controllable from the command-line, assuming the application has such logic. That said, use of nonstandard option syntax in the Go community, for example, is maddening.

2) Environment variables. Personally I usually support environment variables which mirror command lines option. For example, FOO_B or FOO_BAR might be equivalent to specifying a -b or --bar command line option.

3) Configuration file. But please don't make it necessary if at all possible.

If I'm writing an application supporting all 3, then the above ordering is also the precedence ordering. A command line option overrides an environment variable which overrides a configuration file setting.

Command line options are constraining because of the flat namespace and because they become unwieldy in large numbers. But that's a good thing. They force you to think critically about semantics and default behaviors, and to make meaningful choices.

Simple key-value configuration files, like JSON or YAML, are IMO the worst choice of all. They just become dumping grounds. If you're going to support a configuration file format, use an expressive, declarative syntax. An HN poster the other day said that systemd's ini file format was declarative. No, it's not! The abstract configuration of systemd is declarative, but systemd's configuration syntax is anything but. Devising an expressive syntax and structure is difficult, but that's the point. It's a way to examine and reexamine your application behavior without ever writing a single line of code. As far as parsing the configuration file, most high-level languages have good PEG libraries which make it easy to write parsers for ad hoc grammars. For C if you're not comfortable using the classic yacc framework then maybe that's a strong hint to avoid a configuration file altogether.


For functions or secrets? For secrets, ephemeral cache files in a ram disk that set variables with proper posix permissions that only allow root and the application to read. The file should be removed when no longer required.

Why? Avoid leaving secrets on a hard drive. Cache them in case our secret store is not reachable. Avoid logging secrets in auditd by keeping them out of arguments.


All three, check out the Viper/Cobra packages for Golang




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: