systems work
This commit is contained in:
parent
c0e4eac2fa
commit
9d43fbccec
@ -1,17 +1,21 @@
|
|||||||
// ## Epochs
|
// ## 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
|
package main
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
func main() {
|
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.
|
// elapsed time since the Unix epoch.
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
secs := now.Unix()
|
secs := now.Unix()
|
||||||
nanos := now.UnixNano()
|
nanos := now.UnixNano()
|
||||||
|
|
||||||
// There is no `UnixMillis`.
|
// Note that there is no `UnixMillis`.
|
||||||
millis := nanos / 1000000
|
millis := nanos / 1000000
|
||||||
println("Secs: ", secs)
|
println("Secs: ", secs)
|
||||||
println("Millis:", millis)
|
println("Millis:", millis)
|
||||||
|
@ -1,19 +1,38 @@
|
|||||||
// ## Spawning Processes
|
// ## 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
|
package main
|
||||||
|
|
||||||
import "os/exec"
|
import "os/exec"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd := exec.Command("ls", "-a", "-l")
|
// Explain
|
||||||
out, err := cmd.Output()
|
dateCmd := exec.Command("date")
|
||||||
if err != nil {
|
dateOut, dateErr := dateCmd.Output()
|
||||||
panic(err)
|
if dateErr != nil {
|
||||||
}
|
panic(dateErr)
|
||||||
fmt.Println("Files:")
|
|
||||||
fmt.Print(string(out))
|
|
||||||
}
|
}
|
||||||
|
fmt.Println("> date")
|
||||||
|
fmt.Println(string(dateOut))
|
||||||
|
|
||||||
// todo: full command lines with bash
|
|
||||||
// todo: piping in stdin
|
// 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
|
$ 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
|
// ## 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
|
package main
|
||||||
|
|
||||||
import "syscall"
|
import "syscall"
|
||||||
@ -7,16 +15,29 @@ import "os"
|
|||||||
import "os/exec"
|
import "os/exec"
|
||||||
|
|
||||||
func main() {
|
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")
|
binary, lookErr := exec.LookPath("ls")
|
||||||
if lookErr != nil {
|
if lookErr != nil {
|
||||||
panic(lookErr)
|
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"}
|
args := []string{"-a", "-l", "-h"}
|
||||||
|
|
||||||
|
// We'll give the command we execute our current
|
||||||
|
// environment.
|
||||||
env := os.Environ()
|
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)
|
execErr := syscall.Exec(binary, args, env)
|
||||||
if execErr != nil {
|
if execErr != nil {
|
||||||
panic(execErr)
|
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
|
// ## 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
|
package main
|
||||||
|
|
||||||
import (
|
import "fmt"
|
||||||
"fmt"
|
import "os"
|
||||||
"os"
|
import "os/signal"
|
||||||
"os/signal"
|
import "syscall"
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
c := make(chan os.Signal, 1)
|
// Go signal notification works by sending `os.Signal`
|
||||||
d := make(chan bool, 1)
|
// 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() {
|
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()
|
||||||
fmt.Println(sig)
|
fmt.Println(sig)
|
||||||
d <- true
|
done <- true
|
||||||
}()
|
}()
|
||||||
fmt.Println("Awaiting signal")
|
// The program will wait here until it gets the
|
||||||
<-d
|
// 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
|
$ go run signals.go
|
||||||
Awaiting signal
|
awaiting signal
|
||||||
^C
|
^C
|
||||||
interrupt
|
interrupt
|
||||||
|
exiting
|
||||||
|
Loading…
x
Reference in New Issue
Block a user