systems work
This commit is contained in:
parent
c0e4eac2fa
commit
9d43fbccec
@ -1,17 +1,21 @@
|
||||
// ## Epochs
|
||||
|
||||
// A common requirement in programms is getting the number
|
||||
// of seconds, milliseconds, or nanoseconds since the Unix
|
||||
// epoch. Here's how to do it in Go.
|
||||
|
||||
package main
|
||||
|
||||
import "time"
|
||||
|
||||
func main() {
|
||||
// Use `time.Now` with `Unix` or `UnixNane` to get
|
||||
// Use `time.Now` with `Unix` or `UnixNano` to get
|
||||
// elapsed time since the Unix epoch.
|
||||
now := time.Now()
|
||||
secs := now.Unix()
|
||||
nanos := now.UnixNano()
|
||||
|
||||
// There is no `UnixMillis`.
|
||||
// Note that there is no `UnixMillis`.
|
||||
millis := nanos / 1000000
|
||||
println("Secs: ", secs)
|
||||
println("Millis:", millis)
|
||||
|
@ -1,19 +1,38 @@
|
||||
// ## Spawning Processes
|
||||
|
||||
// Sometimes our Go programs need to spawn other, non-Go
|
||||
// processes. For example, the syntax highlighting in this
|
||||
// book is implementing by spawning a [`pygmentize`]()
|
||||
// process from a Go program. Let's look at a few
|
||||
// examples of spawning processes from Go.
|
||||
|
||||
package main
|
||||
|
||||
import "os/exec"
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
cmd := exec.Command("ls", "-a", "-l")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("Files:")
|
||||
fmt.Print(string(out))
|
||||
// Explain
|
||||
dateCmd := exec.Command("date")
|
||||
dateOut, dateErr := dateCmd.Output()
|
||||
if dateErr != nil {
|
||||
panic(dateErr)
|
||||
}
|
||||
fmt.Println("> date")
|
||||
fmt.Println(string(dateOut))
|
||||
|
||||
// todo: full command lines with bash
|
||||
// todo: piping in stdin
|
||||
|
||||
// Note that when spawning commands we need to
|
||||
// provide an explicit command and argument array,
|
||||
// vs. being able to just pass in one command line.
|
||||
// If you want to be able to just spawn a full
|
||||
// command, you can use `bash`'s `-c` option:
|
||||
lsCmd := exec.Command("bash", "-c", "ls -a -l -h")
|
||||
lsOut, lsErr := lsCmd.Output()
|
||||
if lsErr != nil {
|
||||
panic(lsErr)
|
||||
}
|
||||
fmt.Println("> ls -a -l -h")
|
||||
fmt.Println(string(lsOut))
|
||||
}
|
||||
|
@ -1 +1,8 @@
|
||||
$ go run spawning-processes.go
|
||||
> date
|
||||
Wed Oct 3 16:40:57 EDT 2012
|
||||
|
||||
> ls -a -l -h
|
||||
drwxr-xr-x 4 mark 136B Oct 3 16:29 .
|
||||
drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
|
||||
-rw-r--r-- 1 mark 1.3K Oct 3 16:28 spawning-processes.go
|
||||
|
@ -1,5 +1,13 @@
|
||||
// ## Exec'ing Processes
|
||||
|
||||
// In the previous chapter we looked at spawning external
|
||||
// process. We do this when we need the functionality
|
||||
// of another process accessable to a running Go process.
|
||||
// In other cases we may just want to completely replace
|
||||
// the current Go process with another process. To do
|
||||
// this we'll use Go's implementation of the `exec`.
|
||||
|
||||
// In this example we'll exec an `ls` command.
|
||||
package main
|
||||
|
||||
import "syscall"
|
||||
@ -7,16 +15,29 @@ import "os"
|
||||
import "os/exec"
|
||||
|
||||
func main() {
|
||||
// We'll need an absolute path to the binary we'd
|
||||
// like to execute. In this case we'll get the path
|
||||
// for `ls`, probably `/bin/ls`.
|
||||
binary, lookErr := exec.LookPath("ls")
|
||||
if lookErr != nil {
|
||||
panic(lookErr)
|
||||
}
|
||||
|
||||
// Exec requires arguments in slice form (as
|
||||
// apposed to one big string). Here we'll give `ls`
|
||||
// a few arguments
|
||||
args := []string{"-a", "-l", "-h"}
|
||||
|
||||
// We'll give the command we execute our current
|
||||
// environment.
|
||||
env := os.Environ()
|
||||
|
||||
// The actual exec call. If this call is succesful,
|
||||
// the execution of our process will end here and it
|
||||
// will be replaced by the `/bin/ls -a -l -h` process.
|
||||
// If there is an error we'll get a return value.
|
||||
execErr := syscall.Exec(binary, args, env)
|
||||
if execErr != nil {
|
||||
panic(execErr)
|
||||
}
|
||||
}
|
||||
|
||||
// todo: note lack of fork
|
||||
|
14
src/071-execing-processes/execing-processes.sh
Normal file
14
src/071-execing-processes/execing-processes.sh
Normal file
@ -0,0 +1,14 @@
|
||||
# Now if we run this we'll see our programm replaced
|
||||
# by `ls`.
|
||||
|
||||
$ go run execing-processes.go
|
||||
$ ls -a -l -h
|
||||
total 16
|
||||
drwxr-xr-x 4 mark 136B Oct 3 16:29 .
|
||||
drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
|
||||
-rw-r--r-- 1 mark 1.3K Oct 3 16:28 execing-processes.go
|
||||
|
||||
# Note that Go does not offer a classic Unix `fork`
|
||||
# function. Usually this isn't an issue though, since
|
||||
# starting goroutines, spawning processes, and execing
|
||||
# processes covers most use cases for `fork`.
|
BIN
src/072-signals/signals
Executable file
BIN
src/072-signals/signals
Executable file
Binary file not shown.
@ -1,27 +1,42 @@
|
||||
// ## Signals
|
||||
|
||||
// Sometines we'd like our Go programs to intelligently
|
||||
// handle Unix signals. For example, we might want a
|
||||
// server to gracefully shutdown when it receives a
|
||||
// `SIGTERM`, or a command-line tool to stop processing
|
||||
// input if it receives a `SIGINT`. Here's how to handle
|
||||
// signals in Go with channels.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
import "fmt"
|
||||
import "os"
|
||||
import "os/signal"
|
||||
import "syscall"
|
||||
|
||||
func main() {
|
||||
c := make(chan os.Signal, 1)
|
||||
d := make(chan bool, 1)
|
||||
// Go signal notification works by sending `os.Signal`
|
||||
// values on a channel. We'll create a channel to
|
||||
// receive these notifications (we'll also make one to
|
||||
// notify us when the program can exit.)
|
||||
sigs := make(chan os.Signal, 1)
|
||||
done := make(chan bool, 1)
|
||||
|
||||
signal.Notify(c, syscall.SIGINT)
|
||||
// `signal.Notify` registers the given channel to
|
||||
// receive notifications of the specified signals.
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func() {
|
||||
sig := <-c
|
||||
// This goroutine makes a blocking receive for
|
||||
// signals. When it gets one it'll print it out
|
||||
// and then notify the program that it can finish.
|
||||
sig := <-sigs
|
||||
fmt.Println()
|
||||
fmt.Println(sig)
|
||||
d <- true
|
||||
done <- true
|
||||
}()
|
||||
fmt.Println("Awaiting signal")
|
||||
<-d
|
||||
// The program will wait here until it gets the
|
||||
// expected signal, and then exit.
|
||||
fmt.Println("awaiting signal")
|
||||
<- done
|
||||
fmt.Println("exiting")
|
||||
}
|
||||
|
||||
// todo: sending signals?
|
||||
|
@ -1,4 +1,9 @@
|
||||
# When we run this program it will block waiting for a
|
||||
# signal. By typing `ctrl-C` (which the
|
||||
# terminal shows as `^C`) we cand send a `SIGNIT` signal,
|
||||
# causing the program to print `interrupt` and then exit.
|
||||
$ go run signals.go
|
||||
Awaiting signal
|
||||
awaiting signal
|
||||
^C
|
||||
interrupt
|
||||
exiting
|
||||
|
Loading…
x
Reference in New Issue
Block a user