This is a creation in Article, where the information may have evolved or changed. People in ' Cloudflare ' are very fond of the Go language. We are in many [internal software projects] (https://blog.cloudflare.com/what-weve-been-doing-with-go/) and larger [piping systems] (https:// blog.cloudflare.com/meet-gatebot-a-bot-that-allows-us-to-sleep/) used in it. But can we go to the next level and use it as the scripting language of our favorite OS Linux?! [Image here] (https://raw.githubusercontent.com/studygolang/gctt-images/master/go-script/gopher-tux-1.png) # # Why consider going to go As a short answer to the scripting language: why not? Go is relatively easy to learn, not redundant and has a powerful ecological library that can be reused to avoid writing all the code from scratch. Some other potential benefits it may bring: * Provide a go-based build system for your go project: The ' Go Build ' command is intended for small self-contained projects. More complex projects typically take the form of building systems or script sets. Why not Go to write these scripts? * Easy-to-use non-privileged package management: If you want to use a third-party library in your script, you can simply use the ' Go get ' command to get it. And since the code being pulled will be installed in your ' Gopath ', using some third-party libraries does not require the privileges of the system administrator (unlike some other scripting languages). This is especially useful in large enterprise environments. * Rapid code prototyping at the early stage of the project: When you do the first iteration of the code, you often need to do a lot of editing, even compiling, and you have to waste a lot of keystrokes in the edit--build-and-check loop. Instead, using Go, you can skip the ' Build ' section and execute the source file immediately. * Strongly typed scripting language: If you have a small input error somewhere in the script, most scripting languages will be executed in the wrong place and then stopped. This may cause your system to be in an inconsistent state (because some statements are executed to change the state of the data and thus pollute the state before the script is executed). With strongly typed languages, many spelling errors can be caught at compile time, so a script with bugs will not run first. # # The current state of the go script it looks like the go script is easy to implement Unix script ShebanG (#! ...) support. [Shebang Line] (Https://en.wikipedia.org/wiki/Shebang_ (Unix)) is the first line of the script, beginning with ' #! ' and specifying that the script interpreter is used to execute the script (for example, ' #!/bin/bash ' or ' #!/usr/bin/env Python '), so no matter what programming language is used, the system knows exactly how to execute the script. Go has used the ' Go run ' command to support the '. Go ' file similar to the interpreter's call, so just add the appropriate shebang line (' #!/usr/bin/env go Run ') to any '. Go ' file, set the executable state of the file, and then you can play happily Play it. However, there is still a problem using go run directly. [Article of this cow B] (HTTPS://GIST.GITHUB.COM/POSENER/73FFD326D88483DF6B1CB66E8ED1E0BD) describes in detail all the issues and potential solutions around ' go run ', but the key points are: * ' go run ' It is important that the script error code is not correctly returned to the operating system, because the error code is one of the most common ways in which multiple scripts interact with each other and the operating system environment. * You cannot create a shebang line in a valid '. Go ' file because the go language does not know how to handle lines that begin with ' # '. Other languages do not have this problem because ' # ' is a way of commenting in most cases, so the final interpreter ignores shebang lines, but the Go comment starts with a '//' and runs at the call with the following error: ' ' package main: Helloscript.go:1:1:illegal character u+0023 ' # ' [This article] (https://gist.github.com/posener/ 73FFD326D88483DF6B1CB66E8ED1E0BD) describes several workarounds for these issues, including the use of a custom wrapper [Gorun] (Https://github.com/erning/gorun) as an interpreter, But none of them offers an ideal solution. You can: * Must use non-standard shebang line, it begins with '//'. This is not technically even a shebang line, but the way the bash shell handles executable text files, so this solution is unique to bash. In addition, byThe specific behavior of ' go run ', this line is quite complex and not obvious (see the example of the original article). * The Gorun custom wrapper must be used in the Shebang line, which is good, but the resulting '. Go ' file cannot be compiled with the standard ' Go build ' command due to the illegal ' # ' character. # # # How Linux performs file OK, looks like the Shebang method doesn't provide us with a comprehensive solution. Is there any other way we can use it? Let's take a closer look at how the Linux kernel executes binary files. When you try to execute a binary/script (or any file with executable bit settings), your shell will end up using the Linux ' Execve ' system call, passing it to the binary file system path, command-line arguments, and currently defined environment variables. The kernel is then responsible for correctly parsing the file and creating a new process with the code in the file. Most of us know that Linux (and many other Unix-like operating systems) use the ELF binary format for their executables. However, one of the core tenets of Linux kernel development is to avoid "Vendor/format lock-in" of any subsystem, which is part of the kernel. As a result, Linux implements a "pluggable" system that allows the kernel to support any binary format-all you need to do is write a correct module that resolves the format you choose. If you study the kernel source code carefully, you will find that Linux supports more binary formats. For example, the recent ' 4.14 ' Linux kernel, we can see that it supports at least 7 binary formats (in-tree modules for various binary formats typically have a ' binfmt_ ' prefix in their name). It is noteworthy that [Binfmt_script] (https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/fs/binfmt_ SCRIPT.C?H=LINUX-4.14.Y) module, which parses the shebang line mentioned above and executes the script on the target system (not everyone knows that shebang support is actually implemented in the kernel itself, not in the shell or other daemons/processes). # # extends supported binary formats from user space but since we think Shebang is not the best choice for Go scripting, it seems that we need something else. Surprisingly, the Linux kernel already has a "other type of" binary support module, which has an appropriate name of ' Binfmt_misc'. This module allows the administrator to dynamically add support for various executable formats from the user space directly through a well-defined ' PROCFS ' interface, with detailed records. Let's follow [document] (https://www.kernel.org/doc/html/v4.14/admin-guide/binfmt-misc.html) and try to set the binary format description for the '. Go ' file. First, the guide tells you to install a special ' Binfmt_misc ' file system to '/proc/sys/fs/binfmt_misc '. If you are using a relatively new Linux distribution based on SYSTEMD, you probably already have a file system installed for you, because by default system installs special mount and automount units for this purpose. To double-check, just run: "' shell$ Mount | grep binfmt_miscsystemd-1 on/proc/sys/fs/binfmt_misc type AutoFS (rw,relatime,fd=27,pgrp=1,timeout=0,minproto=5, Maxproto=5,direct) "' Another way is to check if there are files in '/proc/sys/fs/binfmt_misc ': properly installed ' binfmt_misc ' file system will create at least two names for ' register ' and ' Status ' special files. Next, because we want our. Go script to correctly pass the exit code to the operating system, we need to use the custom Gorun wrapper as our "interpreter": "shell$ go get github.com/erning/gorun$ sudo mv ~ /go/bin/gorun/usr/local/bin/' Technically speaking, we don't need to move Gorun to '/usr/local/bin ' or any other system path, and anyway ' binfmt_misc ' requires the full path of the interpreter, However, the system can run this executable file with any permissions, so restricting file access from a security perspective is a good idea. At this point, let's build a simple go script ' helloscript.go ' and verify that we can "explain" it successfully. The script is as follows: "' Gopackage mainimport (" 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)} ' ' checks whether parameter passing and error handling work as expected: ' ' shell$ gorun Helloscript.gohello, world!$ echo $?0$ gorun helloscript.go Gopherhello, gopher!$ Echo $?0$ gorun helloscript.go Failhello, fail!$ echo $?30 ' ' Now we need to tell the ' Binfmt_misc ' module How to use ' Gorun ' Line '. Go ' file. As described in the documentation we need to configure the following string: ': Golang:e::go::/usr/local/bin/gorun:oc ', meaning to tell the system: when encountering an executable file with the '. Go ' extension, use the '/usr/local/bin/ The Gorun ' interpreter executes the file. The ' OC ' flag at the end of the string ensures that the script will execute based on the owner information and permission bits set by the script itself, rather than those bits set on the interpreter binaries. This makes the Go script perform the same behavior as other executables and scripts in Linux. Let's register our new Go script binary format: "' shell$ 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 "If the system is successfully registered, it should be in the '/proc/sys/fs/ The new Golang file is displayed under Binfmt_misc ' directory. Finally, we can execute our. Go file locally: ' ' shell$ chmod u+x helloscript.go$./helloscript.gohello, world!$./helloscript.go Gopherhello, gopher!$/helloscript.go Failhello, fail!$ echo $?30 ' ' That's it! Now we can edit the helloscript.go to our liking and see the next time we execute the file.Changes will be immediately visible. In addition, unlike previous shebang, we can use ' go build ' to compile a file into a real executable file at any time.
via:https://blog.cloudflare.com/using-go-as-a-scripting-language-in-linux/
Author: ignat korchagin Translator: Shniu proofreading: polaris1119
This article by GCTT original compilation, go language Chinese network honor launches
This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove
1717 Reads