systems work

This commit is contained in:
Mark McGranaghan 2012-10-03 16:59:58 -04:00
parent c0e4eac2fa
commit 9d43fbccec
8 changed files with 115 additions and 30 deletions

View File

@ -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)

View File

@ -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))
}

View File

@ -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

View File

@ -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

View 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

Binary file not shown.

View File

@ -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?

View File

@ -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