- gosh -c 'command' runs the command and exits, so gosh works as login shell for ssh host command, scp and rsync - gosh script runs a script file, lines starting with # are skipped - without a terminal, commands are read from stdin (byte by byte, so started commands can read the rest of stdin) - the exit status is the one of the last command (127 not found, 126 not executable, 128+n killed by signal n) - -i forces interactive mode, -l/--login is accepted Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gosh eine einfache Shell, geschrieben in golang.
gosh - Go Shell
Version: 0.2.1 (branch: main, commit: 03e791c)
Built-in commands:
cd [dir] - Change directory (cd with no args goes to home)
pwd - Print working directory
echo [args] - Echo arguments
exit [code] - Exit shell with optional status code
quit [code] - Quit shell with optional status code
set VAR=val - Set environment variable
export VAR=val - Export environment variable
help - Show this help
Features:
- Argument parsing with quotes and escapes ('...' is literal,
"..." expands variables, \ escapes the next character)
- Ctrl+D to exit, Ctrl+C to cancel the current line or command
- Command history (up/down arrows), stored in
$XDG_STATE_HOME/gosh/history (default ~/.local/state/gosh/history,
override with $GOSH_HISTFILE); lines starting with a space are not saved
- Tab completion for commands and file paths
- Tilde expansion (~, ~/path) at the start of unquoted words
- Colored prompt (user@host green, red for root; directory blue),
configurable with $GOSH_COLORS, e.g. GOSH_COLORS='user=1;33:path=36'
(keys user, root, path; values are ANSI SGR codes, empty = no color);
disabled with $NO_COLOR, TERM=dumb or when output is not a terminal
- Environment variable expansion ($VAR, ${VAR}, ${VAR:-default});
using an unset variable is an error, use ${VAR:-} for an empty default
- Non-interactive use: gosh -c 'command', gosh script, command | gosh;
the exit status is the one of the last command
Aufruf
gosh [-l] [-i] [script]
gosh [-l] -c command
gosh -version
| Aufruf | Verhalten |
|---|---|
gosh |
interaktive Shell (wenn stdin ein Terminal ist) |
gosh -c 'befehl' |
führt den Befehl aus und beendet sich |
gosh skript.gosh |
führt das Skript Zeile für Zeile aus |
befehle | gosh |
liest die Befehle von stdin |
-i |
erzwingt den interaktiven Modus, auch ohne Terminal |
-l, --login |
Login-Shell (wird akzeptiert, eine Startdatei gibt es noch nicht) |
Ohne Terminal bricht gosh bei einem fehlgeschlagenen Befehl nicht ab und beendet sich mit dem Exit-Status des letzten Befehls: 127, wenn ein Befehl nicht gefunden wurde, 126, wenn er nicht ausführbar ist, 128+n, wenn er durch Signal n beendet wurde. Leere Zeilen und Zeilen, die mit # beginnen, werden übersprungen, Skripte können also mit #!/usr/bin/gosh beginnen.
Damit funktionieren auch ssh host befehl, scp und rsync, wenn gosh als Login-Shell gesetzt ist. Da gosh ;, && und Pipes noch nicht kennt, darf der Befehl dabei aber nur aus einem einfachen Kommando bestehen.
Farben
Der Prompt wird über die Umgebungsvariable GOSH_COLORS eingefärbt. Sie besteht aus durch : getrennten Einträgen schlüssel=code:
| Schlüssel | Teil des Prompts | Standard |
|---|---|---|
user |
user@host |
1;32 (fett grün) |
root |
user@host, wenn man root ist |
1;31 (fett rot) |
path |
aktuelles Verzeichnis | 1;34 (fett blau) |
Die Werte sind ANSI-SGR-Codes, mehrere werden mit ; kombiniert:
1fett,2blass,3kursiv,4unterstrichen30–37Vordergrund,90–97helle Vordergrundfarben,40–47Hintergrund38;5;Neine der 256 Farben,38;2;R;G;BTruecolor (sofern das Terminal es kann)
Nicht angegebene Schlüssel behalten ihre Standardfarbe, ein leerer Wert (path=) schaltet die Farbe für diesen Teil ab. Ungültige Werte werden ignoriert. Da nur Ziffern und ; erlaubt sind, lassen sich über die Variable keine beliebigen Escape-Sequenzen ins Terminal schreiben. NO_COLOR schaltet alle Farben ab.
Gesetzt wird die Variable z. B. in ~/.profile oder direkt in gosh (wirkt ab dem nächsten Prompt):
export GOSH_COLORS='user=1;33:path=1;36' # in ~/.profile
set 'GOSH_COLORS=user=1;33:path=1;36' # in gosh
Ein paar Kombinationen zum Ausprobieren:
# Solarized: gelb und cyan
GOSH_COLORS='user=33:path=36'
# Sonnenuntergang: orange und pink (256 Farben)
GOSH_COLORS='user=1;38;5;208:path=38;5;205'
# Matrix: hellgrün und blassgrün
GOSH_COLORS='user=1;92:path=2;32'
# Dracula: lila und pink (Truecolor)
GOSH_COLORS='user=1;38;2;189;147;249:path=38;2;255;121;198'
# Nord: frostblau und hellgrau (Truecolor)
GOSH_COLORS='user=1;38;2;136;192;208:path=38;2;216;222;233'
# Ozean: türkis und kursiv blau
GOSH_COLORS='user=1;96:path=3;94'
# Root-Warnung: weiß auf rotem Hintergrund
GOSH_COLORS='root=1;97;41'
# Dezent: nur das Verzeichnis unterstrichen
GOSH_COLORS='user=:path=4'
Sicherheitshinweise
- Die History liegt in
$XDG_STATE_HOME/gosh/history(Standard:~/.local/state/gosh/history) und ist nur für den eigenen Benutzer lesbar (Verzeichnis0700, Datei0600). MitGOSH_HISTFILElässt sich ein anderer Pfad setzen, mitGOSH_HISTFILE=wird die History abgeschaltet. - Zeilen, die mit einem Leerzeichen beginnen, werden nicht in der History gespeichert – praktisch für Befehle mit Passwörtern oder Tokens.
- Innerhalb von
'...'wird nichts expandiert,\$ergibt ein wörtliches$. - Eine nicht gesetzte Variable bricht den Befehl ab (wie
set -u), damit z. B.rm -rf $DIR/outnie mit leerem$DIRausgeführt wird. Für einen Standardwert${VAR:-default}bzw.${VAR:-}verwenden. - Variablenwerte werden nicht in mehrere Wörter aufgeteilt.
- Steuerzeichen in Verzeichnisnamen werden im Prompt escaped angezeigt (z. B.
\x1b), Dateien mit Steuerzeichen im Namen werden nicht vervollständigt. - Ctrl+C beendet nur den laufenden Befehl bzw. verwirft die aktuelle Zeile, nicht die Shell.
gosh is not meant for production use, it is just a proof of concept.
building
go build ./
Die Version lässt sich mit gosh -version (oder --version, -V) abfragen und steht auch in der Ausgabe von help:
$ gosh -version
gosh 0.2.1 (branch: main, commit: 03e791c)
Version und Branch werden beim Bauen mit GoReleaser per -ldflags gesetzt. Bei einem einfachen go build steht dort dev, der Commit wird dann aus den von Go eingebetteten Git-Informationen gelesen (mit -dirty, falls es uncommittete Änderungen gab).
Release
Binaries sowie .deb- und .rpm-Pakete werden mit GoReleaser gebaut (Konfiguration: .goreleaser.yaml).
# lokal testen, ohne etwas zu veröffentlichen (Ergebnis in dist/)
goreleaser release --snapshot --clean
# Release auf Gitea veröffentlichen
export GITEA_TOKEN=...
git tag -a v0.1.0 -m "v0.1.0"
git push origin v0.1.0
goreleaser release --clean
Das Paket installiert /usr/bin/gosh und trägt die Shell in /etc/shells ein, sodass sie mit chsh -s /usr/bin/gosh gesetzt werden kann.