この記事はCloudflareによるUsing Go as a scripting language in Linuxの内容そのまんまである。
TLDR
Linuxカーネルには/proc/sys/fs/binfmt_misc
という仕組みがあり、指定の拡張子/マジックコードに対して指定のインタープリタを実行させることができる。この機能を使って、Goのソースファイルを./helloscript.go
で実行できるようにする。
例として使うGoのソースファイルは下記の通り。shebangなどは要らない。
helloscript.go
package main
import (
"fmt"
"os"
)
func main() {
s := "world"
if len(os.Args) > 1 {
s = os.Args[1]
}
fmt.Printf("Hello, %v!", s)
fmt.Println("")
if s == "fail" {
os.Exit(30)
}
}
やりかた
Using Go as a scripting language in Linuxに書いてある通り。
# binfmt_miscの機能が有効になっているか確認
$ mount | grep binfmt_misc
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=27,pgrp=1,timeout=0,minproto=5,maxproto=5,direct)
# プロセスのEXIT STATUSがちゃんとOSに渡せるようにするため、ラッパーとしてgorunを入れる
$ go get github.com/erning/gorun
$ sudo mv ~/go/bin/gorun /usr/local/bin/
# binfmt_miscの設定
$ echo ':golang:E::go::/usr/local/bin/gorun:OC' | sudo tee /proc/sys/fs/binfmt_misc/register
:golang:E::go::/usr/local/bin/gorun:OC
# スクリプトに実行属性をつける
$ chmod u+x helloscript.go
# 実行する(出来上がり!)
$ ./helloscript.go
Hello, world!