Where is the $HOME environment variable set?

17

4

I'm looking for the place where $HOME environment variable set. It is after login, to my mind.

I'm using Linux debian 2.6.32-5-686.

webnoon

Posted 2011-04-17T11:56:56.273

Reputation: 273

Answers

2

If you are attempting to modify your HOME, you can do

export HOME=/home/... 

either in your shell, or in your ~/.profile file and/or ~/.bashrc (or appropriate login shell).

(The above code will work for bash and similar shells, which are default in Debian; you would otherwise do `setenv HOME $HOME:/extra/path I think on csh-like shells in other distros.)

edit -- However this is probably not the way to do it. See other answers. Do not use this answer.

user76871

Posted 2011-04-17T11:56:56.273

Reputation: 791

You are likely confusing $HOME with $PATH. It does not make sense to have multiple paths in $HOME (the entire value will be treated as a single pathname) or, in most cases, to modify $HOME at all. – user1686 – 2012-09-09T20:55:06.787

@grawity: oops sorry, thank you. Sadly I cannot delete my answer. – user76871 – 2012-09-10T02:37:12.493

22

On Linux, the HOME environment variable is set by the login program:

  • by login on console, telnet and rlogin sessions
  • by sshd for SSH connections
  • by gdm, kdm or xdm for graphical sessions.

user1686

Posted 2011-04-17T11:56:56.273

Reputation: 283 655

8

The login program arranges it before calling exec on your shell (by including it in the arguments to exec), based on the value in /etc/passwd.

bmargulies

Posted 2011-04-17T11:56:56.273

Reputation: 1 121

1Interesting this did not get more votes. It's the only answer that actually specifies where the environment variable is set, which was the OP's actual question. – Mike Williamson – 2018-09-02T19:42:12.903

5

Edit this by running: usermod -d /home/whatever_dir whatever_user.

Please note that this will (obviously) be the new home directory. Bash will cd to it on login, so make sure it exists and the permissions are correct. In addition, don't forget about .bashrc, .profile, .xinitrc, etc; if they're not in the home directory, they will not be read.

From usermod:

Usage: usermod [options] LOGIN

Options:
  -c, --comment COMMENT         new value of the GECOS field
  -d, --home HOME_DIR           new home directory for the user account
  -e, --expiredate EXPIRE_DATE  set account expiration date to EXPIRE_DATE
  -f, --inactive INACTIVE       set password inactive after expiration
                                to INACTIVE
  -g, --gid GROUP               force use GROUP as new primary group
  -G, --groups GROUPS           new list of supplementary GROUPS
  -a, --append                  append the user to the supplemental GROUPS
                                mentioned by the -G option without removing
                                him/her from other groups
  -h, --help                    display this help message and exit
  -l, --login NEW_LOGIN         new value of the login name
  -L, --lock                    lock the user account
  -m, --move-home               move contents of the home directory to the
                                new location (use only with -d)
  -o, --non-unique              allow using duplicate (non-unique) UID
  -p, --password PASSWORD       use encrypted password for the new password
  -R, --root CHROOT_DIR         directory to chroot into
  -s, --shell SHELL             new login shell for the user account
  -u, --uid UID                 new UID for the user account
  -U, --unlock                  unlock the user account

Synthead

Posted 2011-04-17T11:56:56.273

Reputation: 221

0

I did some digging, and the answer to this is a bit surprising. Take the following test script and chmod +x it:

#!/bin/bash 
printf 'My home is: '
echo  ~ || echo 'nowhere'

We can run it with ./test.sh and see:

My home is: /home/user

Let's take a peek under the hood with strace.

$ strace ./test.sh |& grep '^open[a-z]*'

openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libtinfo.so.5", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/dev/tty", O_RDWR|O_NONBLOCK) = 3
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
openat(AT_FDCWD, "./test.sh", O_RDONLY) = 3

I do not see any mention of HOME, rc files, or passwd. Let's try it with a clean env:

env -i bash
echo $HOME  #this will be blank since we cleared the env

Nothing, as expected. Let's run the script in the blank env.

env -i bash
./test.sh 

My home is: /home/user

Interesting, the script is able to get home. Now let's trace.

strace ./test.sh |& grep '^open[a-z]*'

Now we see:

openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libtinfo.so.5", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/dev/tty", O_RDWR|O_NONBLOCK) = 3
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_compat.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_nis.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnsl.so.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "./test.sh", O_RDONLY) = 3

I've bolded the interesting lines. As we can see, it would appear that when $HOME is not defined, the shell will try to fill it in, even when not in login or interactive mode.

DeusXMachina

Posted 2011-04-17T11:56:56.273

Reputation: 113