Skip to content

Commit b54847f

Browse files
authored
docs: improve examples even further (#240)
Signed-off-by: Carlos Alexandro Becker <[email protected]>
1 parent 3b7f41d commit b54847f

File tree

3 files changed

+78
-32
lines changed

3 files changed

+78
-32
lines changed

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ We recommend you follow the examples in the following order:
55
## Basics
66

77
1. [Simple](./simple)
8+
1. [Graceful Shutdown](./graceful-shutdown)
89
1. [Server banner and middleware](./banner)
910
1. [Identifying Users](./identity)
1011
1. [Multiple authentication types](./multi-auth)

examples/graceful-shutdown/main.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"errors"
6+
"net"
7+
"os"
8+
"os/signal"
9+
"syscall"
10+
"time"
11+
12+
"github.com/charmbracelet/log"
13+
"github.com/charmbracelet/ssh"
14+
"github.com/charmbracelet/wish"
15+
"github.com/charmbracelet/wish/logging"
16+
)
17+
18+
const (
19+
host = "localhost"
20+
port = "23234"
21+
)
22+
23+
func main() {
24+
srv, err := wish.NewServer(
25+
wish.WithAddress(net.JoinHostPort(host, port)),
26+
wish.WithHostKeyPath(".ssh/id_ed25519"),
27+
wish.WithMiddleware(
28+
func(next ssh.Handler) ssh.Handler {
29+
return func(sess ssh.Session) {
30+
wish.Println(sess, "Hello, world!")
31+
next(sess)
32+
}
33+
},
34+
logging.Middleware(),
35+
),
36+
)
37+
if err != nil {
38+
log.Error("Could not start server", "error", err)
39+
}
40+
41+
// Before starting our server, we create a channel and listen for some
42+
// common interrupt signals.
43+
done := make(chan os.Signal, 1)
44+
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
45+
46+
// We then start the server in a goroutine, as we'll listen for the done
47+
// signal later.
48+
go func() {
49+
log.Info("Starting SSH server", "host", host, "port", port)
50+
if err = srv.ListenAndServe(); err != nil && !errors.Is(err, ssh.ErrServerClosed) {
51+
// We ignore ErrServerClosed because it is expected.
52+
log.Error("Could not start server", "error", err)
53+
done <- nil
54+
}
55+
}()
56+
57+
// Here we wait for the done signal: this can be either an interrupt, or
58+
// the server shutting down for any other reason.
59+
<-done
60+
61+
// When it arrives, we create a context with a timeout.
62+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
63+
defer func() { cancel() }()
64+
65+
// When we start the shutdown, the server will no longer accept new
66+
// connections, but will wait as much as the given context allows for the
67+
// active connections to finish.
68+
// After the timeout, it shuts down anyway.
69+
log.Info("Stopping SSH server")
70+
if err := srv.Shutdown(ctx); err != nil && !errors.Is(err, ssh.ErrServerClosed) {
71+
log.Error("Could not stop server", "error", err)
72+
}
73+
}

examples/simple/main.go

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
package main
22

33
import (
4-
"context"
54
"errors"
65
"net"
7-
"os"
8-
"os/signal"
9-
"syscall"
10-
"time"
116

127
"github.com/charmbracelet/log"
138
"github.com/charmbracelet/ssh"
@@ -48,32 +43,9 @@ func main() {
4843
log.Error("Could not start server", "error", err)
4944
}
5045

51-
// Before starting our server, we create a channel and listen for some
52-
// common interrupt signals.
53-
done := make(chan os.Signal, 1)
54-
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
55-
56-
go func() {
57-
log.Info("Starting SSH server", "host", host, "port", port)
58-
if err = srv.ListenAndServe(); err != nil && !errors.Is(err, ssh.ErrServerClosed) {
59-
// We ignore ErrServerClosed because it is expected.
60-
log.Error("Could not start server", "error", err)
61-
done <- nil
62-
}
63-
}()
64-
65-
// Here we wait for the done signal.
66-
// When it arrives, we create a context and start the shutdown.
67-
<-done
68-
69-
// When we start the shutdown, the server will no longer accept new
70-
// connections, but will wait as much as the given context allows for the
71-
// active connections to finish.
72-
// After the timeout, it shuts down anyway.
73-
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
74-
defer func() { cancel() }()
75-
log.Info("Stopping SSH server")
76-
if err := srv.Shutdown(ctx); err != nil && !errors.Is(err, ssh.ErrServerClosed) {
77-
log.Error("Could not stop server", "error", err)
46+
log.Info("Starting SSH server", "host", host, "port", port)
47+
if err = srv.ListenAndServe(); err != nil && !errors.Is(err, ssh.ErrServerClosed) {
48+
// We ignore ErrServerClosed because it is expected.
49+
log.Error("Could not start server", "error", err)
7850
}
7951
}

0 commit comments

Comments
 (0)