Rootssh from Mac OS with Homebrew fails with netcat

I saw the 5-Jun-2023 blog post on changes in ROOT, including the web-based version of TBrowser. This would greatly simplify my ROOT tutorial, so I decided to give it a try.

I’m using a Apple Studio M1 running Mac OS Ventura 13.4. I use Homebrew as a package manager. I ran:

brew install root
brew install netcat

(I discovered that I needed the latter after I tried rootssh for the first time.) I then tried to run rootssh:

# rootssh
Use local port 7575 for root_socket /tmp/root.sbU8XwGu0 redirection from
netcat: invalid option -- U
Try `netcat --help' for more information.
Command not recognized  - stop

The remote machine myserver is running AlmaLinux 9, 6.28/04, Built for linuxx8664gcc, g++ (GCC) 11.3.1. I also installed netcat on the remote server, just in case, but that changed nothing.

Sure enough, when I type netcat --help and man netcat on both systems, the Homebrew version of netcat does not have the -U option, though the Linux version does.

A quick glance using:

less `which rootssh`

shows that indeed the command netcat -U is part of the script, with no tests against program or OS version, or whether the program is capable of handling UNIX-domain sockets.

Am I doing something wrong? Is this a bug in rootssh? Or am I missing something?

ROOT Version: 6.28/04
Platform: MacOS Ventura 13.4, Built for macosxarm64
Compiler: Apple clang version 14.0.3

Hi @seligman,

Historically, there is more than one implementation of netcat, most importantly the GNU and the OpenBSD one. I guess rootssh relies on the latter, which allows to use UNIX domain sockets via the -U option.
(FYI, @linev)

However, macOS should already bundle the BSD version as /usr/bin/nc – therefore, in principle, no need to install the netcat package from brew.
Given that on most systems where netcat is installed, nc is a symlink to netcat, perhaps we should use nc in the rootssh script instead, @linev (?).


FWIW, I checked on MacOS:

# which nc

# which netcat

# netcat --help
GNU netcat 0.7.1, a rewrite of the famous networking tool.
Basic usages:
connect to somewhere:  netcat [options] hostname port [port] ...
listen for inbound:    netcat -l -p port [options] [hostname] [port] ...
tunnel to somewhere:   netcat -L hostname:port -p port [options]

Mandatory arguments to long options are mandatory for short options too.
  -c, --close                close connection on EOF from stdin
  -e, --exec=PROGRAM         program to exec after connect
  -g, --gateway=LIST         source-routing hop point[s], up to 8
  -G, --pointer=NUM          source-routing pointer: 4, 8, 12, ...
  -h, --help                 display this help and exit
  -i, --interval=SECS        delay interval for lines sent, ports scanned
  -l, --listen               listen mode, for inbound connects
  -L, --tunnel=ADDRESS:PORT  forward local port to remote address
  -n, --dont-resolve         numeric-only IP addresses, no DNS
  -o, --output=FILE          output hexdump traffic to FILE (implies -x)
  -p, --local-port=NUM       local port number
  -r, --randomize            randomize local and remote ports
  -s, --source=ADDRESS       local source address (ip or hostname)
  -t, --tcp                  TCP mode (default)
  -T, --telnet               answer using TELNET negotiation
  -u, --udp                  UDP mode
  -v, --verbose              verbose (use twice to be more verbose)
  -V, --version              output version information and exit
  -x, --hexdump              hexdump incoming and outgoing traffic
  -w, --wait=SECS            timeout for connects and final net reads
  -z, --zero                 zero-I/O mode (used for scanning)

Remote port number can also be specified as range.  Example: '1-1024'

# nc --help
nc: unrecognized option `--help'
usage: nc [-46AacCDdEFhklMnOortUuvz] [-K tc] [-b boundif] [-i interval] [-p source_port]
	  [--apple-recv-anyif] [--apple-awdl-unres]
	  [--apple-boundif ifbound]
	  [--apple-no-cellular] [--apple-no-expensive]
	  [--apple-no-flowadv] [--apple-tcp-timeout conntimo]
	  [--apple-tcp-keepalive keepidle] [--apple-tcp-keepintvl keepintvl]
	  [--apple-tcp-keepcnt keepcnt] [--apple-tclass tclass]
	  [--tcp-adp-rtimo num_probes] [--apple-initcoproc-allow]
	  [--apple-tcp-adp-wtimo num_probes]
	  [--setsockopt-later] [--apple-no-connectx]
	  [--apple-delegate-pid pid] [--apple-delegate-uuid uuid]
	  [--apple-kao] [--apple-ext-bk-idle]
	  [--apple-netsvctype svc] [---apple-nowakefromsleep]
	  [--apple-notify-ack] [--apple-sockev]
	  [--apple-tos tos] [--apple-tos-cmsg]
	  [-s source_ip_address] [-w timeout] [-X proxy_version]
	  [-x proxy_address[:port]] [hostname] [port[s]]

It’s as you said: netcat doesn’t have the -U option in Homebrew, but nc has the -U option in Darwin.

I suppose as a work-around I could try removing the Homebrew netcat, then alias netcat to nc. I may give it a try later.

1 Like

I gave it a try. An alias did not work (since rootssh runs in a sub-shell) so I used a symbolic link instead. However, I got stuck on a different step:

# cd /opt/homebrew/bin
# /opt/homebrew/bin > ln -sf /usr/bin/nc netcat
# /opt/homebrew/bin > cd

# rootssh seligman@myserver
Use local port 7221 for root_socket /tmp/root.mH1CbHzTo redirection from seligman@myserver

[07:11:47][myserver:~]$ root
  | Welcome to ROOT 6.28/04               |
  | (c) 1995-2022, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on May 08 2023, 02:44:07                 |
  | From tags/v6-28-04@v6-28-04                                      |
  | With g++ (GCC) 11.3.1 20221121 (Red Hat 11.3.1-4)                |
  | Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q'  |

root [0] TBrowser tb

ROOT comes with a web-based browser, which is now being started. 
Revert to TBrowser by setting "Browser.Name: TRootBrowser" in rootrc file or
by starting "root --web=off"
Web-based TBrowser can be used in batch mode when starting with "root -b --web=server:8877"
Find more info on
Info in <THttpEngine::Create>: Starting HTTP server on port x/tmp/root.mH1CbHzTo
/opt/homebrew/bin/rootssh: line 59: xdg-open: command not found
                                                               netcat: Address already in use
                                                                                             Command not recognized  - stop
   (TBrowser &) Name: Browser Title: ROOT Object Browser

Evidently rootssh expects to find xdg-open on the local operating system. I checked, and the xdg-open command is not available via Homebrew. There is a complicated procedure for getting xdg-open installed, but it seems like a “cure worse than the disease”:

Looking at the rootssh script, it looked like I could use a browser other than xdg-open. But I can’t figure out the argument parsing:

# rootssh --browser=firefox seligman@myserver
Use local port 7768 for root_socket /tmp/root.bjWwedX2d redirection from seligman@tanya
seligman@myserver: illegal option -- -
usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]
           [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
           [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]
           [-i identity_file] [-J [user@]host[:port]] [-L address]
           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
           [-Q query_option] [-R address] [-S ctl_path] [-W host:port]
           [-w local_tun[:remote_tun]] destination [command [argument ...]]
/opt/homebrew/bin/rootssh: line 149: 25070 Killed: 9               $0 --as-listener-- $listener_local $localport $browser

# rootssh seligman@myserver --browser=firefox
Use local port 7689 for root_socket /tmp/root.7luRvsrcQ redirection from seligman@myserver
bash: line 1: --browser=firefox: command not found
Connection to myserver closed.
/opt/homebrew/bin/rootssh: line 149: 25096 Killed: 9               $0 --as-listener-- $listener_local $localport $browser

I’m looking for a process that makes the students’ lives easier, not a lesson in package dependencies.

I’m going to make a guess: rootssh has only been tested from a local Linux system to a remote Linux system. Since most of my students have either Mac or Windows laptops, may I request that the rootssh script accommodate those systems as well?

A closer reading of the rootssh page suggests that there should be no = after the --browser option. I tried:

# rootssh --browser firefox seligman@myserver

That gave me:

/opt/homebrew/bin/rootssh: line 59: firefox: command not found

I experimented with the Darwin open command, and confirmed that

# open /Applications/

worked on MacOS. Then I tried:

# rootssh --browser /Applications/ seligman@myserver

which gave me the error

/opt/homebrew/bin/rootssh: line 59: /Applications/ is a directory

If this is the level of difficulty I’m experiencing on Darwin, I wonder if someone using WSL on Windows would experience the same kind of problems.

Yes, xdg-open is a thing (Linux only, I guess). Given that it depends on the XDG specification, I would not try to install it on anything that is not GNU/Linux.

xdg-open basically takes care of spawning the associated application to deal with the specified file/URL. Given that it is the used in rootssh to open the default browser, I guess you can achieve the same effect by using the macOS open command as in:

$ rootssh --browser open seligman@myserver

I will create a GitHub issue to improve the rootssh script on macOS (CC: @linev).


@seligman, this is now tracked here Properly support macOS in `rootssh` · Issue #13215 · root-project/root · GitHub.

Indeed, that works! Thanks!

Because I’m so used to the classic TBrowser, this new web-based TBrowser is confusing to me. In particular, I find that the TreeViewer is not intuitive. But that’s another topic altogether.

1 Like


I provide PR for rootssh : Adjust rootssh for usage on Mac by linev · Pull Request #13218 · root-project/root · GitHub

Can you test it?
Just download modified version and try to run it.

You do not need to install full ROOT on your client machine where just web browser is required.


Thanks for the rapid response, Sergey. Unfortunately, I think you’re going to need fancier scripting. I tried it, but got the “xdg-open: command not found” message again.

The issue is that your script tests against the variable $OSTYPE. On my remote Linux server, it has this value:

# echo $OSTYPE

On my Mac desktop:

echo $OSTYPE

While I suppose you can modify your code to just look for ‘darwin’ as a substring, might I suggest an “evidence-based” approach that might be applicable to a greater range of operating systems? Something like:

# List of potential local client browsers
browsers=( xdg-open open )
for b in "${browsers[@]}"
    # test if the browser is available.
    which ${b} 2>&1 >/dev/null
    if [ $? -eq 0 ]; then
    # The search was successful. 

if [ -z "${browser}" ]; then
    echo "No appropriate browser found; please use --browser option"
    exit 1

That way, when we learn which ‘browser’ is appropriate for Windows or WSL, you can just add it to the browsers array and not clutter your script with a bunch of nested if statements. (Hmm… can a bash script even execute in the Windows command shell?)

1 Like

I update PR - can you try now?

That works, at least on my system. Thanks!

1 Like


It also works for me, therefore I can commit it to master.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.