I was looking for a simple way to interact with the various machines in my house.  A lot of the stuff that runs uses simple shell commands.  I found a post on how someone did it with Go here:  http://techfeast-hiranya.blogspot.com/2015/06/expose-any-shell-command-or-script-as.html

Previously, I've used mixed scripts to run tasks on remote machines over SSH or installed things like EventGhost on Windows to listen for events.  While that stuff works, this is an easier way to manage things.  So, I thought I would have it autobuild some common binaries for Windows, Linux, and MacOS through docker.  https://github.com/leonowski/go-shell-api-docker

It autobuilds on Dockerhub here with this image name:  


The container itself is just a dummy container.  It won't actually do anything.  The best thing to do is to just run it temporarily to copy the automatic builds out.  For example:

docker run -v "$(pwd)":/temp --rm -it leonowski/go-shell-api-docker sh -c "cp -R /go-shell-api-bins/* /temp/"


Usage of ./go-shell-api:
-b string
Path to the executable binary
-p int
HTTP port to listen on (default 8080)


go-shell-api -b ls

This will start an HTTP server listening on port 8080.  An HTTP get will return the output of the command 'ls' to the HTTP client.

curl http://some-server:8080

To add parameters to the shell command, use POST:

curl -X POST -d "-ls /home/user" http://some-server:8080 (equivalent of ls -ls /home/user)

Practical Ways to Use This

I use Home Assistant home automation software to control everything in my home.  It integrates with everything imaginable.  Exposing things via HTTP makes things easy to work with.  One easy thing to do is to use Home Assistant's Command line Switch integration.  This allows me to define a switch using shell commands.  My particular setup to turn on my Street Fighter V arcade machine looks like this in Home Assistant:

    command_on: wakeonlan 7582C6324498
    command_off: curl --silent -X POST -d "/s /t 0"
    friendly_name: Arcade Machine
    command_state:  /config/arcade_machine_status.sh
    value_template: '{{ value == "0" }}'
Configuration for my arcade machine


That example is probably bad.  Going back and forth between shell and HTTP is confusing.  I have since updated my config in Home Assistant to use a special "rest_command" feature along with something called a "light_template" to present the Arcade machine as a "light" in Home Assistant.  That way, it understands "on" and "off" and Alexa knows about it too.  So, it looks something like this in Home Asisstant:

    url: ''
    method: POST
    payload: 'ab:cd:6f:f2:04:ac'
    url: ''
    method: POST
    payload: '1'
  - platform: template
        friendly_name: "Arcade"
          service: rest_command.set_arcade_on
          service: rest_command.set_arcade_off

You can still use the command line features though in Home Assistant if you need to do something funky with your HTTP request and mix the on or off commands to use some combination.  The flexibilty of Home Assistant is its strength.  In this better example, I POST a mac address to an endpoint that will run WOL.  This endpoint is actually running on my router so I never have to find a binary or do something funky to send a magic WOL packet.  I just have to use a REST endpoint now!  (I guess that would be another blog post).

The go-shell-api binary is run on startup by a Windows machine using a scheduled task.  The command invoked is go-shell-api.exe -b shutdown.  So, when I ask Home Assistant to turn off the machine, it sends a POST to with the data "/s /t 0" which tells the machine to shut down immediately.  To turn on the machine a wakeonlan request is sent to the specified MAC address.  Finally, I can check the state of the machine using a script that calls nc to see if anything is listening on port 8080 on the remote machine.  The value template simply checks the exit status of the script and if true, the machine is considered on.

Another way I use it is to control my sprinklers.  My frontyard sprinklers are connected to an old Raspberry pi with some relay controlled by GPIO.  I simply set up a new systemd unit file to start up with a command line GPIO command:

Description=Sprinkler HTTP interface

ExecStartPre=/usr/bin/gpio mode 11 out
ExecStart=/home/pi/go-shell-api/go-shell-api -p 8181 -b "gpio write 11"

systemd unit file for my sprinkler

After that, I simply need to POST a 1 to turn on the sprinkler or a 0 to turn it off.

Now, you can do something crazy with all of this and have it run something like bash or sh.  You can then post something like "-c 'other commands'" That would then let you do anything you want - but that's crazy and you probably shouldn't do that.