16

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
  • 551
  • 4
  • 6
  • 16
  • Why don't you just copy `/usr/bin/zsh` to `/bin/zsh`? – Lenniey Jan 18 '17 at 12:31
  • 1
    @Lenniey That way you're creating a loose copy that won't be updated together with the original. – Mario Jan 18 '17 at 12:43
  • @Mario whelp...of course you're right. OP: don't ever do that! ;) – Lenniey Jan 18 '17 at 12:45
  • 1
    @Lenniey - The copy needs to go the other way! And if you can copy, then you can link. – AFH Jan 18 '17 at 12:50
  • @AFH yeah my comment is a complete mess... – Lenniey Jan 18 '17 at 13:16
  • 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 Jan 18 '17 at 15:24
  • 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 Jan 18 '17 at 15:49
  • @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 Jan 19 '17 at 07:08
  • @AFH: I just see from the response given by Dimitar, that even enabling the root user would not help in my case.... – user1934428 Jan 19 '17 at 07:12
  • 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 Jan 19 '17 at 14:39
  • 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 Jan 20 '17 at 13:17

1 Answers1

19

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
  • 799
  • 6
  • 12
  • 2
    You'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 Jan 18 '17 at 12:45
  • Well yes, you're correct, he has to edit the scripts (which can happen with a single command). – 13dimitar Jan 18 '17 at 12:47
  • @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 Jan 18 '17 at 12:58
  • 1
    note taken, I've modified my answer – 13dimitar Jan 18 '17 at 13:02