How to create symbolic links in /usr/bin on a Mac?

11

4

Environment: OSX Sierra, Darwin Kernel Version 16.3.0

Root Problem: I want to use a bunch of shell scripts in a central repository, which have a #!/usr/bin/zsh. On my Mac, the zsh is in /bin/zsh.

Attempted solution: I want to create a symbolic link

ln -s /bin/zsh /usr/bin/zsh

My user account has admin rights, but I am not root, and I would prefer not to enable the root user on this Mac. Therefore I first did a

sudo su

to get a shell with root privileges and then executed the ln command. However I still get the error message ln: /usr/bin/zsh: Operation not permitted.

Questions:

  • Why do I get this error message?

  • What would have I to do to create the link?

  • Is there a better way to achieve my original goal? Note that fixing the #! lines is not an option.

user1934428

Posted 2017-01-18T12:25:10.840

Reputation: 253

Why don't you just copy /usr/bin/zsh to /bin/zsh? – Lenniey – 2017-01-18T12:31:48.620

1@Lenniey That way you're creating a loose copy that won't be updated together with the original. – Mario – 2017-01-18T12:43:53.450

@Mario whelp...of course you're right. OP: don't ever do that! ;) – Lenniey – 2017-01-18T12:45:59.233

1@Lenniey - The copy needs to go the other way! And if you can copy, then you can link. – AFH – 2017-01-18T12:50:00.270

@AFH yeah my comment is a complete mess... – Lenniey – 2017-01-18T13:16:49.767

If the file system is supported in Linux, then boot a LiveCD (I use Ubuntu) and you should be able to create the link after mounting the file system. Ubuntu Live boots into root, so just bring up a terminal and use your command there. I am slightly surprised to find that /usr is among the protected directories (see Dimitar's answer): on Ubuntu this is where most applications install. – AFH – 2017-01-18T15:24:27.243

If this doesn't work, then the only option is to create a front end to each of the scripts, using mkdir $HOME/scripts;cd PathToScripts;for f in *; do echo -e "#/bin/zsh\n. PathToScripts/$f >$HOME/scripts/$f and add export PATH=$HOME/scripts:$PATH to .bashrc. This is simplified by assuming that none of the scripts, $HOME, nor $PATH contains spaces or other zsh special characters. The solution uses two things: (1) by placing the local script directory at the head of $PATH the local front ends will always be found first; and (2) the . command ignores #! as simply a comment. – AFH – 2017-01-18T15:49:24.200

@AFH: This can't seriously be the only solution! I mean: OSX is basically BSD Unix - I don't think Apple expects the users to buy a separate Linux system, just for doing admin tasks on their machine! Before going this way, I would rather activate the root user for my system. This would for sure work, but I'm looking for an alternative way. – user1934428 – 2017-01-19T07:08:08.460

@AFH: I just see from the response given by Dimitar, that even enabling the root user would not help in my case.... – user1934428 – 2017-01-19T07:12:36.630

Most Linux distributions are free, so you don't need to buy it. I suggested this work-round only because of Dimitar's comment "please don't do it". But the real problem is with the script provider: every shell should have an entry in /bin/, and the real solution is to get the script writer to use the correct, compatible script header #!/bin/zsh. Just for the record, Ubuntu has entries in both directories, symbolic links to separate entries in/etc/, which link back to /bin/zsh5, a binary executable! Make of that what you will. – AFH – 2017-01-19T14:39:29.727

Of course I don't need to buy the Linux system, but I would need a separate PC for this. I would like to have symbolic links, and this is how I would solve this on Linux, but unfortunately I can't do this on the Mac. – user1934428 – 2017-01-20T13:17:38.793

Answers

14

You get this message because of Apple's System Integrity Protection. System Integrity Protection includes protection for these parts of the system:

/System
/usr
/bin
/sbin
Apps that are pre-installed with OS X

Paths and apps that third-party apps and installers can continue to write to include:

/Applications
/Library
/usr/local

This means that you can simply create a symbolic link in /usr/local/bin (it's still in your $PATH).

BUT, it seems that you specifically need to create the symbolic link in /usr/bin. You can achieve it by disabling System Integrity Protection (please don't do it, just edit the scripts..). You can disable it by (I haven't tested it myself!!!):

Click the  menu.
Select Restart...
Hold down command-R to boot into the Recovery System.
Click the Utilities menu and select Terminal.
Type csrutil disable and press return.
Close the Terminal app.
Click the  menu and select Restart....

13dimitar

Posted 2017-01-18T12:25:10.840

Reputation: 701

2You've missed the point: the questioner has scripts which specify #!/usr/bin/zh as the shell, so the solution he seeks is to link this location to where the shell actually resides, but as you say he is protected from doing this. Unless the protection is bypassed, the only solution would seem to be a batch edit of the scripts. – AFH – 2017-01-18T12:45:45.133

Well yes, you're correct, he has to edit the scripts (which can happen with a single command). – 13dimitar – 2017-01-18T12:47:52.077

@Dimitar look at the question: Is there a better way to achieve my original goal? Note that fixing the #! lines is not an option. – Lenniey – 2017-01-18T12:58:02.887

1note taken, I've modified my answer – 13dimitar – 2017-01-18T13:02:30.750