A high-performance interactive Shell written from scratch in Go. A system-level interactive command-line interpreter implemented from scratch, deeply simulating core Bash mechanisms.
English Version | ไธญๆ็ๆฌ
**Gosh** is a lightweight, modular Unix-like Shell implementation. It adopts a modern **decoupled architecture design**, completely separating Parsing, Execution, and Builtins.This project deeply practices the Unix philosophy, implementing efficient multi-stage pipelines and file descriptor redirection through Go concurrency. It is an excellent example for learning operating system process management, IPC communication, and lexical analysis.
- Multi-stage Pipelines (
|): Supports infinite pipeline operations, automatically managing I/O resources and lifecycles of parent-child processes.- Example:
ls -l | grep ".go" | wc -l
- Example:
- Advanced I/O Redirection:
- Input Redirection:
wc -l < input.txt - Output Overwrite:
echo "hello" > output.txt - Output Append:
echo "world" >> output.txt - Error Stream Redirection:
ls not_exist 2> error.log(Supports2>>append).
- Input Redirection:
cd: Change directory (supports intelligent expansion of~to the user's home directory).pwd: Display current working directory.echo: Echo text, supports parameter concatenation.history: Powerful history management (supports-wwrite /-rread).type: Command type detection (distinguishes between Built-in and External).exit: Safely exit and persist history.
- Line Editing Enhancement: Integrated
readlinelibrary, supporting cursor movement, deletion, and history backtracking. - Smart Completion: Pressing the
Tabkey automatically completes commands or file paths. - State Persistence: Saves history via the
HISTFILEenvironment variable or default strategy, preventing loss upon restart.
This project performs deep module partitioning and logical encapsulation in its underlying implementation:
- Global Control: Maintains Shell global variables and standardizes I/O streams (Stdin/Stdout/Stderr), primarily for use by built-in commands in the
builtinsdirectory. - Convenient Initialization: Provides a
NewSessionfactory method for one-click environment initialization.
- Pipeline Splitting: The
Parsefunction first physically splits the input string using the|symbol as a delimiter, then encapsulates it into the Pipeline struct for storage. - Tokenization (Lexer):
parseTokenhandles finer-grained parsing, processing escape logic for single quotes (') and double quotes ("), further disassembling the string separated by|into concrete Command units. At the low level, a Command is converted into a[]stringslice. - Redirection Parsing:
parseSingleCommandperforms deep parsing on concrete commands, capable of identifying and processing 5 types of I/O stream redirection (<,>,>>,2>,2>>).- Key Logic: At this stage, the parser removes I/O redirection identifiers and filenames, purifying the character fragments maintained within the Command into purely "Instruction Name + Arguments", while encapsulating the redirected filenames and modes separately in the Command struct.
- Channel Construction (Execute): The main function of this is to build I/O channels for commands.
- It iterates through
command.args, first handling pipeline redirection logic. - It maintains temporary I/O objects internally, constructing file redirections and opening corresponding files based on flags set by the Parse layer.
- If the current command is not the last in the Pipeline, it builds an
os.Pipechannel for connection.
- It iterates through
- Command Scheduling (startSingleCommand):
- Used to specifically invoke or execute command operations.
- Concurrency Safety: For built-in commands, an extra Goroutine is constructed for execution to ensure the main function continues running and maintains memory safety, passing errors (
err) through channels. - Unified Interface: Adopts the
WaitFuncinterface form to standardize the exit waiting logic of the main function (whether waiting for internal goroutines or external processes).
- Function Mapping: Designs internal command operations, mapping command strings to processing functions via a
CodFuncmap, ensuring concrete function interfaces are not exposed outside the package. - Unified Interface: Uses
CommandFuncas the unified implementation interface for all built-in command functions, guaranteeing feasibility of direct function invocation via mapping loops. - Extensibility: To extend command-line opcodes, simply add corresponding logic in the concrete implementation functions.
- Myshell: The entry point of the entire program, initializing
SessionandReadline. - Real-time Interaction: Implements real-time input reading, capturing user input and entering the REPL loop.
โโโ cmd/
โ โโโ myshell/
โ โโโ main.go # Program entry: Responsible for Session initialization and REPL main loop
โ โโโ readline.go # Readline configuration and auto-completion logic
โโโ internal/
โ โโโ builtins/ # Builtin command layer: CodFunc mapping and concrete implementation
โ โโโ executor/ # Execution engine layer: Execute channel construction and startSingleCommand scheduling
โ โโโ parser/ # Parsing layer: Pipeline splitting and redirection symbol stripping
โ โโโ session/ # State layer: Global Session management
---
## ๐ฆ Installation & Usage
### Prerequisites
* Go 1.18 or higher
* Linux / macOS environment (Path handling on Windows may differ slightly)
### Quick Run
```bash
# 1. Download dependencies
go mod tidy
# 2. Run Shell
go run cmd/myshell/main.go
# Compile
go build -o gosh cmd/myshell/main.go
# Start
./gosh
1. Basic Commands and Pipelines
$ ls -l | grep "main.go"
2. File Writing and Reading
# Overwrite
$ echo "Hello Gosh" > hello.txt
# Append
$ echo "Another line" >> hello.txt
# Input Redirection
$ cat < hello.txt
3. Error Log Processing
# Redirect standard error output to file
$ ls /file_not_exist 2> error.log
4. History Operations
# Manually save history to specified file
$ history -w my_history_backup.txt
Pull Requests are welcome. To-Do List (TODO):
- Support environment variable setting (
export). - Support logical operators (
&&,||). - Support background jobs (
&).
MIT License