matryer / xbar

Put the output from any script or program into your macOS Menu Bar (the BitBar reboot)
https://xbarapp.com
MIT License
17.56k stars 643 forks source link

Interpreted Go exec format error #694

Open aaronedell opened 3 years ago

aaronedell commented 3 years ago

I have a Go file that starts with:

//path/to/go run $0 $@; exit

In the plugin browser, it looks good, all the metadata is interpreted correctly and the variable shows up editable as expected, but the plugin won't run. I get the error fork/exec ./001-myplugin.1h.go: exec format error.

When I run the plugin in the terminal with ./ it runs fine. I've run chmod +X as well, still getting the error.

matryer commented 3 years ago

Hey @aaronedell - thanks for opening this. I'll look into what's going on with it.

aaronedell commented 3 years ago

Thanks. My guess is it's probably something INSIDE the computer that's causing the problem. Hope that helps.

matryer commented 3 years ago

@aaronedell thanks, we'll start there.

aaronedell commented 3 years ago

A friend of mine was asking how its going?

matryer commented 3 years ago

The only idea I have is to explicitly notice that it's a .go file, and have specific code to handle that case. But tbh, I don't love that idea.

matryer commented 3 years ago

@leaanthony @ianfoo Have you seen anything like this before?

leaanthony commented 3 years ago

Multiple Go versions and wrong one on path for Arch? -x usually the culprit.

aaronedell commented 3 years ago

I forgot to mention, I'm on go version go1.12.3 darwin/amd64

matryer commented 3 years ago

@aaronedell it might be worth trying a more up-to-date version of Go, just in case, but I doubt that's it.

aaronedell commented 3 years ago

Yeah I tried that :( sadly no such luck

On May 1, 2021, at 2:35 AM, Mat Ryer @.***> wrote:

 @aaronedell it might be worth trying a more up-to-date version of Go, just in case, but I doubt that's it.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

elalemanyo commented 3 years ago

Hi, I am having also some problems when I try to run a go based plugin. Because my go path is: /usr/local/bin/go my shebang is: //usr/local/bin/go run $0 $@; exit I update go, go version is 1.16.3 The plugin script runs perfectly in Terminal: go run [script.10s.go] but xbar tells: fork/exec ./script.10s.go: exec format error 🤷‍♂️

BTW: is ok having go.mod and go.sum in plugins folder?

Thanks

matryer commented 3 years ago

@leaanthony Do you have any ideas about this? It's stumped me. As far as I know, there should be no reason why this isn't working. Does the exec stuff in Go work differently to running it in a terminal?!

mlvnd commented 3 years ago

// is not a valid shebang (needs to be #!) and therefore not used by the kernel for exec-ing the interpreter. When executed with a shell, the first line just runs the command the path points to (for example /usr/local/bin/go or /usr/bin/true; exec /usr/bin/env go run "$0" "$@". Double slashes just get ignored. If you use ///bin/echo Hi there in the first line, and run it from a shell, you'll notice it just prints "Hi there" and runs the rest of the script.

If you don't mind spawning an extra process, starting it from a shell might be a solution: cmd := exec.CommandContext(ctx, "sh",command).

Edit: Ah, just noticed you got some good feedback on Twitter already. My bad, I might have jumped too eagerly on this nice little puzzle. Anyway, I learned some stuff, so I'm happy.

aaronedell commented 3 years ago

Sorted?

image

johncalvinroberts commented 3 years ago

Hoi there. Sorry to barge in and everything but was there any update on a workaround here?

mlvnd commented 3 years ago

Hi John, as a workaround, I started putting my go scripts in a go directory inside the plug-in directory.

As an example, ~/Library/Application Support/xbar/plugin/my-plugin.10s contains:

#!/bin/sh
exec /usr/local/bin/go run go/$0.go $@

Which would run ~/Library/Application Support/xbar/plugin/go/my-plugin.10s.go.

Edit: I'd like to point out that the workaround I mentioned is flawed too. According to the docs, the name of the plugin should be in the form {name}.{time}.{ext} and the way I did it, I left out the .{ext} part. As a result, it will not run at the desired interval.

leaanthony commented 3 years ago

What's the real fix here? The exec? Just curious

mlvnd commented 3 years ago

Hi Lea, the reason it worked, is because of the shebang. Upon executing the file, the kernel inspects the shebang and runs sh as the interpreter of the script.

The exec was only there to eliminate the extra process. If you remove the command from the script, the process tree looks like xbar > sh > go run. With exec it will look like xbar > go run.

mlvnd commented 3 years ago

For those still looking for a solution: If you can live with some trade-offs then gorun might be what you're looking for. With gorun installed (go install github.com/erning/gorun@latest), you can just use the real shebang like this:

#!/path/to/gorun
package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
}
jackielii commented 1 year ago

For those still looking for a solution: If you can live with some trade-offs then gorun might be what you're looking for. With gorun installed (go install github.com/erning/gorun@latest), you can just use the real shebang like this:

#!/path/to/gorun
package main

import (
  "fmt"
  "time"
)

func main() {
  fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
}

This seems the only solution works so far, on macos.

On Linux, there is an more reliable alternative: https://blog-cloudflare-com.webpkgcache.com/doc/-/s/blog.cloudflare.com/using-go-as-a-scripting-language-in-linux/