System wide variables across all users and all shells. How?

Hello all!

What is the best way to define system wide variable that will be available for all users under any of shells?

Means seeking solutions that not require me to define something for each of user separately in ~/.profile or ~/.login.conf or any other files. Means seeking solution to define it at one place for every user under any of shells.
 
I've once tried defining environment variables for all user on/etc/rc.conf[.local], without luck.
Not tried, but
  • creating something like /etc/login.local (for /bin/[t]csh as shell)
  • for variables for base components and site-local ones,
  • /usr/local/etc/login.local for anything others (needed only for ports components and host-local ones)
  • /usr/local/etc/login.conf is included from /etc/login.local if exists (conditionally).
  • /etc/login.local alone is included from ~/.login of all users.
could work.

Note that how to define environment variables depends on the shell used, so these configuration files shoule be prepared for all type of shells (/bin/sh, /bin/csh, /usr/local/bin/zsh, and so on) used in the host separately.
 
[…] What is the best way to define system wide variable that will be available for all users under any of shells?
Do you mean you declare one variable and if one user changes the variable’s value, all other logged‑in users see that changed variable’s value, too? This is not possible. Well, at least not without effort.​

If you mean, you set the initial environ(7)ment variable’s value but otherwise each user maintains their own independent copy: There’s /etc/login.conf(5), there’s /etc/profile (sh(1) and many shells(5) consult this file), there’s pam_putenv(3) (should you program a PAM module) … familiarize with each of them to assess what’s the best for your situation.​
 
Yep, setenv from login.conf(5) is probably the first option to look at in the described scenario if we are talking about any shell.
It would be. But I'm not 100% sure if it always promised to work for shell scripts invoked by nologin users (usually for daemons) and every shells in the wild (including ones which does not in ports collection).
 
It would be. But I'm not 100% sure if it always promised to work for shell scripts invoked by nologin users (usually for daemons) and every shells in the wild (including ones which does not in ports collection).

I think that if you come in via a ssh command (not a login) there are shells that don't load any dotfiles. I also think FreeBSD's /bin/sh is one.
 
It would be. But I'm not 100% sure if it always promised to work for shell scripts invoked by nologin users (usually for daemons) and every shells in the wild (including ones which does not in ports collection).
You're right about the scripts, I just thought OP was asking about interactive shells.

And yes, sh(1) doesn't source any files by default unless invoked as a login shell, but it can (again, if run interactively) if the ENV variable is set.
 
What about a kenv setting instead of env ?
Would that fit the ticket?
That should be across all login tpyes.
Contents of kenv doesn't seem to be included in environment variables.
So modifying (maybe) /sbin/init should be needed to propagate kenv as environment variables for it.
 
What is the best way to define system wide variable that will be available for all users under any of shells?
XY problem: Why do you want this? What is the use? What problem are you really trying to solve?

The fact that Unix-style systems have not provided this concept in about 50 years shows that there must be other good ways to solve whatever the need is. Probably better ways.

Other operating systems used to have such facilities; for example, VMS had system-wide logical names.
 
What about using the variable as a sysctl value? That should be easily readable but also easily writable without reboot or hacking.
Both kenv and sysctl will work if you need to share variables between your own programs (since they'll know exactly where to look), but then it might make more sense to just use a file. The problem is that other programs are quite stubborn and will only check places they were programmed to check, e.g. the user environment.
 
XY problem: Why do you want this? What is the use? What problem are you really trying to solve?
What came in my mind is the format of outputs from ifconfig(8).
If there are any scripts/binaries depending on it and default format is changed (i.e., legacy HEX to CIDR), the admin would need to switch back to HEX until all scripts/binaries are fixed and confirmed to be OK for CIDR. This shall be system-wide.
 
Both kenv and sysctl will work if you need to share variables between your own programs (since they'll know exactly where to look), but then it might make more sense to just use a file. The problem is that other programs are quite stubborn and will only check places they were programmed to check, e.g. the user environment.
sysctl should need hack, too, if I understand correctly.
sysctl/tunable (technically the same with different option) need to be held in kernel and/or kernel modules. No way to define and use new ones at run time without loading kernel module which defines them.

Correct me if I'm mis-understanding and/or overlooking something.
 
No way to define and use new ones at run time without loading kernel module which defines them.
Yes, for some reason I was thinking only about already existing sysctls. In any case, these mechanisms (both kenv and sysctl) are intended to manipulate the environment/state of the kernel, and their use for other purposes (like some kind of userland IPC) of course shouldn't be considered as a real option.
 
What is this then? Straight out of the manual. Where does it say only intended to manipulate/state kernel?

Code:
       The following is    an example of how to create a new  top-level  category
       and  how     to  hook up another subtree to    an existing static node.  This
       example does not    use contexts, which results in tedious    management  of
       all intermediate    oids, as they need to be freed later on:

         #include <sys/sysctl.h>
          ...
         /*
          *    Need to    preserve pointers to newly created subtrees,
          *    to be able to free them    later:
          */
         static struct sysctl_oid *root1;
         static struct sysctl_oid *root2;
         static struct sysctl_oid *oidp;
         static int    a_int;
         static char *string = "dynamic sysctl";
          ...

         root1 = SYSCTL_ADD_ROOT_NODE(NULL,
             OID_AUTO, "newtree", CTLFLAG_RW, 0, "new top level    tree");
         oidp = SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(root1),
             OID_AUTO, "newint", CTLFLAG_RW, &a_int, 0,    "new int leaf");
          ...
         root2 = SYSCTL_ADD_NODE(NULL, SYSCTL_STATIC_CHILDREN(_debug),
             OID_AUTO, "newtree", CTLFLAG_RW, 0, "new tree under debug");
         oidp = SYSCTL_ADD_STRING(NULL, SYSCTL_CHILDREN(root2),
             OID_AUTO, "newstring", CTLFLAG_RD,    string,    0, "new    string leaf");

       This example creates the    following subtrees:

         debug.newtree.newstring
         newtree.newint

       Care should be taken to free all    OIDs once they are no longer needed!
 
What is this then? Straight out of the manual. Where does it say only intended to manipulate/state kernel?
As eseipi noted, the manual page you introduced is for kernel codes built into kernel and/or kernel modules. From man(1):
Code:
     The sections of the manual are:
           1.   FreeBSD General Commands Manual
           2.   FreeBSD System Calls Manual
           3.   FreeBSD Library Functions Manual
           4.   FreeBSD Kernel Interfaces Manual
           5.   FreeBSD File Formats Manual
           6.   FreeBSD Games Manual
           7.   FreeBSD Miscellaneous Information Manual
           8.   FreeBSD System Manager's Manual
           9.   FreeBSD Kernel Developer's Manual
 
Well since I already look silly how about a memdisk on boot and copy a file to it.
Strore the variable there.

Read a line from variables file on memdisk or even /var
If you can't get an environment to work try another way. All kind of programs store 'variables' in files.
 
Back
Top