Shell CLI challenge: as root, create symlink to a location on a location for a different user

This is not a real problem. I just noticed this CLI admin dilemma.
I have a script that adds 4 predefined users to a target FreeBSD installation dir. It runs as root. All users of the target system have file aaa in their home directory. They also require a symlink to this file named bbb

As root, how do I create symlink ~/bbb to ~/aaa for a different user? Problem is that ~/ gets translated to /root because root runs it. All users get a /home/root/bbb symlink but it should point to each user's own home directory. I can't find a solution for this except a post-installation action to fix the symlink names for all non-root users.

As root, how do I create symlink ~/bbb to ~/aaa for a different user's home directory? I have the feeling I'm missing something simple...
 
Hm, I never used that. Was expecting something liike this but only tried with /. Kind of stupid. 😑
 
Bash:
srcfile=/root/file
for i in user1 user2 user3 user4; do
    destfile="/home/$i/file"
    ln -s $srcfile $destfile # -s required if not on same filesystem
done
# permissions issues are left as exercise for OP
 
Bash:
srcfile=/root/file
for i in user1 user2 user3 user4; do
    destfile="/home/$i/file"
    ln -s $srcfile $destfile # -s required if not on same filesystem
done
# permissions issues are left as exercise for OP
The source file should be ~/file for all users, pointing to their own home dir. Problem was that ~/file gets translated to /root/file always because root runs this code.
~<user> does avoid that.
 
The source file should be ~/file for all users, pointing to their own home dir. Problem was that ~/file gets translated to /root/file always because root runs this code.
~<user> does avoid that.
Quit using the tilde and parse the password file then.
 
for a in user1 user2 user3 user4; do (cd ~$a; ln -s aaa bbb; chown $a bbb); done If these users are not on the system where you run the script, you can chroot to $target before doing this.
 
Quit using the tilde and parse the password file then.
I thought the idea of it was to make referencing to the home dir of different users universal. They can all use the same application that installs things there. It's also time-efficient at manual CLI operation. ~ = my homedir. I often use >~/a to store some output temporarily without typing a full path.
 
for a in user1 user2 user3 user4; do (cd $a; ln -s aaa bbb; chown $a bbb); done If these users are not on the system where you run the script, you can chroot to $target before doing this.
True but every program you run inside the chrootdir has to be there including dll's. /bin/ln needs libc and libstdbuf.
 
I often use >~/a to store some output temporarily without typing a full path.
The shell will look up /etc/passwd to interpret ~$user so if this is not shared with the target, you have to locate target's password file but if you use chroot $target, it will lookup the appropriate passwd file.
 
The shell will look up /etc/passwd to interpret ~$user so if this is not shared with the target, you have to locate target's password file but if you use chroot $target, it will lookup the appropriate passwd file.
So ~ stands for the 7th field of the passwd file? I thought it was a POSIX demand that all shells comply with.
It still works without the password files, though. It's not using $HOME?
 
It can (and probably does) use $HOME for ~ but I am talking about ~$randomUser.
Everything before the / is the homedirs path only?
It's the $HOME dir. export HOME="" ends ~ interpretation. I think /usr/bin/login remembers it because it reads de passwd file anyway and passes it to the shell.
 
So ~ stands for the 7th field of the passwd file? I thought it was a POSIX demand that all shells comply with.
POSIX™ doesn’t require /etc/passwd, but yeah:​
If the tilde-prefix consists of only the <tilde> character, it shall be replaced by the value of the variable HOME. If HOME is unset, the results are unspecified.
[…]
If the characters in the tilde-prefix following the <tilde> form a portable login name, the tilde-prefix shall be replaced by a pathname of the initial working directory associated with the login name. The pathname shall be obtained as if by using the getpwnam() function […]
That's what I'd do:
# grep "username" /etc/passwd | awk -F: '{print $6}'
At least anchor username, i. e. ^username:; username alone may inadvertently match multiple times.​
[…] I don't see any good reason to do it a different way to get that information.
Primarily because MG knows said users exist – ~existent_user is sufficient (assuming portable user name). If you are not sure, you want to cause and recognize an error. Secondarily nsswitch.conf(5), you are excluding network user accounts. Finally, /etc/passwd is non‑authoritative, FreeBSD uses /etc/pwd.db / spwd.db.​
Bash:
getent passwd "${USER:?}" | {
	IFS=':' read -r login_name password UID GID GECOS home shell && \
	printf '%s\n' "${home:?Aw shucks, $login_name is homeless.}"
}
I have a script that adds 4 predefined users to a target FreeBSD installation dir. […]
How are you creating those users? You know pw(8) has a ‑k parameter, you could just prepare an appropriate skeleton_directory.​
 
POSIX™ doesn’t require /etc/passwd, but yeah:

At least anchor username, i. e. ^username:; username alone may inadvertently match multiple times.
Primarily because MG knows said users exist – ~existent_user is sufficient (assuming portable user name). If you are not sure, you want to cause and recognize an error. Secondarily nsswitch.conf(5), you are excluding network user accounts. Finally, /etc/passwd is non‑authoritative, FreeBSD uses /etc/pwd.db / spwd.db.​
Bash:
getent passwd "${USER:?}" | {
    IFS=':' read -r login_name password UID GID GECOS home shell && \
    printf '%s\n' "${home:?Aw shucks, $login_name is homeless.}"
}
How are you creating those users? You know pw(8) has a ‑k parameter, you could just prepare an appropriate skeleton_directory.​
Fair points, though the point of parsing out the /etc/passwd is to confirm that the home directory is where you think it is and isn't a nonstandard one for one reason or another. The OP from the sound of it already knows whether or not to worry about network accounts. The OP already knows who the user names are and if we're messing around with the RE for finding the user name then anchoring it isn't enough, and I never implied that it was. Just anchoring it isn't going to guarantee that you don't have the sitation of username2 and username22 showing up or the like and whatever RE is being used needs backup in terms of the verification returning exactly 1 result and it being the expected result.

Portability is nice to consider, however, I don't see anything here to indicate that it needs to be.
 
the tilde (~) is an alias for the HOME environment variable. It will point to whatever you set HOME to be. If the somewhat obscurely described goal is to do something in the user directories of each user then parsing /etc/passwd is the answer. You also get uid and gid so setting target file permissions becomes trivial when executed as root.

Quit making it harder than it has to be!
 
Back
Top