9

I am writing a package for something that requires an environment variable to be set in order to execute properly. Should the install step of a package manager modify a user's environment, or simply prompt the user to do so themselves? My intuition would be the latter, but I can see arguments for the former.

David Cowden
  • 2,903
  • 17
  • 23
  • 7
    Can you make that something behave better, removing the dependency on the environment variable (e.g., using a config file instead)? That would be preferable to packaging hacks or mucking with `.bashrc`, I think. –  May 27 '14 at 19:11
  • Sure, but let's say for the purpose of this question that modifying the application is not an option. – David Cowden May 27 '14 at 19:12
  • 1
    What if the user isn't running `bash`? There are many alternative shells available with a wide variety of startup files. I seriously suggest finding some alternative solution here. – Jules May 28 '14 at 05:20
  • 10
    So write a wrapper around it. See, for instance, `tomcat`, which needs several environment variables to function correctly; they're all set by a startup script that is run instead of running its binary directly. – Jules May 28 '14 at 05:55
  • But what if the user doesn't have `sh` installed? – David Cowden May 28 '14 at 05:59
  • It seems a little backwards to me to imagine that the user doesn't have `sh`, but has `bash`. – Pandu May 28 '14 at 08:49
  • @DavidCowden On every sane system that has bash, bash provides a symlink named sh which runs bash in a bourne shell compatible mode. Jules has a great solution here, it is definitely worth considering. – Vality May 28 '14 at 10:27
  • 1
    @Vality I know. Jules' proposal has been suggested already. I'm being facetious--making fun of the circular logic involved to first argue that I should have a shell agnostic solution then proceed to suggest I use a shell script as the solution. It's a joke (; – David Cowden May 28 '14 at 10:38
  • @DavidCowden Ah, fair enough. This is an interesting problem actually, :) though I get you now. +1 – Vality May 28 '14 at 10:56
  • @Vality well a shell script at least allows the writer to specify `!# which/shell` the system should execute the script using, whereas @Jules point is that setting the environment explicitly in something like `~/.bash[rc|_profile]` pins you to *bash*, specifically. – David Cowden May 28 '14 at 16:12

6 Answers6

18

Should the install step of a package manager modify a user's environment, or simply prompt the user to do so themselves?

Neither. Package installers should never touch anything in a home directory for an account the package doesn't own. Packages should also configure themselves so that if they're installed, they're usable without any special effort on the user's part. (There are exceptional cases where you don't want to do this, but they're few and far between.)

Unixy environments have a place to put configuration files that are read whenever a user starts a login shell. For the Bourne and C shells, you can insert your configuration into /etc/profile and /etc/csh.cshrc respectively. (Don't forget to remove it when you uninstall.)

Many systems also support doing this using individual files, which makes it easier to add and remove bits of configuration without having to drop text into some arbitrary place in one file. (It also gives you all of the control and accountability benefits you get from a package manager.) Some distributions will configure /etc/profile read all files matching /etc/profile.d/*.sh.

Blrfl
  • 20,235
  • 2
  • 49
  • 75
  • 1
    Historically, `rc` in a script name [derives from CTSS `runcom`](http://www.faqs.org/docs/artu/ch10s03.html#ftn.id2941902) (Run Commands), but has since broadened in scope to include other meanings. – Jeffrey Hantin May 27 '14 at 22:02
  • 1
    @JeffreyHantin: Touché. Removed. – Blrfl May 27 '14 at 22:22
  • 1
    Hate to keep picking, but `profile.d` isn't built into bash, it's a [hook commonly provided](http://www.linuxfromscratch.org/blfs/view/svn/postlfs/profile.html) from (usually the distro's base) `/etc/profile`. ;) – Jeffrey Hantin May 27 '14 at 22:56
  • 1
    @JeffreyHantin: True enough, although there will be no criticism of my use of the word "Unixy." :-) – Blrfl May 27 '14 at 23:16
14

It's never acceptable to modify a user's /home structure from the package manager unless that modification is the entire point.

The main approaches to this are:

  • Notify the user they need to configure it.
  • Supply defaults so it's not needed
  • Package a launcher script that sets the values appropriately
  • (If the distro supports it) Drop a file exporting the environment variable inside /etc/profile.d. On some linux systems, all scripts in this directory are sourced by the default shell setup, so you can safely set the variable there.
Daenyth
  • 8,077
  • 3
  • 31
  • 46
7

Question Should the install step of a package manager modify a user's environment?

Answer No. It's a bad idea to modify a user's data, in this case the .bashrc file. User's data should be considered sacred by a package manager?

Question Should the install step of a package manager simply prompt the user to do so themselves?

Answer This is a lot more palatable solution but still not ideal.

I think you should create a wrapper shell script where you can set the necessary environment variables and them run the executable after that.

R Sahu
  • 1,966
  • 10
  • 15
  • I've considered this idea too. The project is young and will get to the point where this shouldn't be necessary. – David Cowden May 27 '14 at 19:37
  • @GlenH7 I updated my response. Hopefully the updated response is more of answer you are looking for. – R Sahu May 27 '14 at 23:20
  • @GlenH7: This question is essentially an XY problem: http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem, where the need for environment variables is the true problem to be solved. – whatsisname May 27 '14 at 23:21
  • Furthermore, this answer's suggestion to create a wrapper script is the only answer that will work for all shells. – whatsisname May 27 '14 at 23:22
  • @GlenH7 We're operating under the assumption that I *need* the environment variable and cannot modify the code installed by the package I'm writing. Obviously this is not ideal, I agree, but the fact that *there exists* another option does not automatically make this an "XY question". – David Cowden May 27 '14 at 23:23
  • The other reason for this of course is - what about all the *other* users on the system (especially ones that don't even exist at the time of the package install), it's all very well and good adjusting files and giving suggestions for the one that did the install, but anyone else logging in is going to be screwed. So, I'd say wrapper script above all other options. – Matt Thomason May 28 '14 at 00:55
  • 1
    @MattThomason that realization is what prompted me to actually ask the question (; – David Cowden May 28 '14 at 04:47
5

You're missing the forest for the trees. Obviously it's more convenient to perform the environment change for the user, but it's also more risky and somewhat invasive. You should combine the best of both worlds by asking the user whether the installer should modify their .bashrc, and otherwise give instructions how they should do it themselves.

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
  • Thanks for the advice. I've never written a public package before and just want to make sure I don't do something taboo. – David Cowden May 27 '14 at 19:37
  • This is how the google cloud SDK handles this today. It asks if you want to modify your startup files. – jmq May 27 '14 at 22:37
1

You're assuming that "user" is singular. What happens if I have thousands of users on this system?

You're assuming that you can even find the home directory of the user. If users are managed through e.g. LDAP you may not even be allowed to get a list of all valid users. The home directories may not be in /home; they may be dynamically mounted from the network. The user's home directory may be encrypted and the key inaccessible while they are not logged in.

There is no way to do this reliably in every possible situation. Use the distro's mechanism for setting environment variables for users as they log in or spawn shells. If that doesn't work, write a wrapper. (The wrapper can also be a binary if necessary, to address the argument in comments).

pjc50
  • 10,595
  • 1
  • 26
  • 29
0

Setting a global variable in a package is acceptable if it's a one defined by your own project(and that means the project's name is part of the variable's name!). Even then, you shouldn't touch the user's .bashrc file - instead you should add a script to /etc/profile.d.

Idan Arye
  • 12,032
  • 31
  • 40