Python实例题:Python 实现简易 Shell
目录
Python实例题
题目
代码实现
功能说明
基本命令执行:
内置命令:
环境变量:
管道:
重定向:
信号处理:
使用方法
注意事项
Python实例题
题目
Python 实现简易 Shell
代码实现
import os
import sys
import shlex
import subprocess
import signalclass SimpleShell:def __init__(self):self.running = Trueself.env = os.environ.copy()self.history = []# 设置信号处理,忽略 Ctrl+Csignal.signal(signal.SIGINT, self._handle_signal)def _handle_signal(self, signum, frame):"""处理信号,如 Ctrl+C"""if signum == signal.SIGINT:print("\nShell 仍在运行... 输入 'exit' 退出。")self.prompt()def prompt(self):"""显示命令提示符"""cwd = os.getcwd()sys.stdout.write(f"{os.path.basename(cwd)}> ")sys.stdout.flush()def read_command(self):"""读取用户输入的命令"""try:line = sys.stdin.readline()if not line: # 处理 EOF (Ctrl+D)print("exit")self.running = Falsereturn ""return line.strip()except KeyboardInterrupt:print()return ""def execute(self, command):"""执行命令"""if not command:returnself.history.append(command)# 内置命令if command.lower() == "exit":self.running = Falsereturnif command.lower() == "history":for i, cmd in enumerate(self.history, 1):print(f"{i}: {cmd}")returnif command.startswith("cd "):try:dir_path = command[3:].strip()if not dir_path:dir_path = self.env.get("HOME", os.path.expanduser("~"))os.chdir(dir_path)except Exception as e:print(f"cd: {e}")return# 处理环境变量设置if "=" in command and not shlex.split(command)[0].startswith("$"):try:var, value = command.split("=", 1)self.env[var] = valuereturnexcept:print("无效的环境变量设置")return# 处理管道if "|" in command:self._handle_pipes(command)return# 处理重定向if ">" in command or "<" in command:self._handle_redirection(command)return# 执行外部命令self._execute_external(command)def _handle_pipes(self, command):"""处理管道命令"""commands = [cmd.strip() for cmd in command.split("|")]processes = []prev_pipe = Nonefor i, cmd in enumerate(commands):args = shlex.split(cmd)# 最后一个命令输出到标准输出if i == len(commands) - 1:stdout = Noneelse:# 创建新的管道r, w = os.pipe()stdout = wnext_stdin = r# 第一个命令从标准输入读取if i == 0:stdin = prev_pipeelse:stdin = next_stdin# 关闭上一个管道的写端if prev_pipe:os.close(prev_pipe)try:pid = os.fork()if pid == 0:# 子进程if stdin:os.dup2(stdin, 0)os.close(stdin)if stdout:os.dup2(stdout, 1)os.close(stdout)# 关闭所有其他管道for p in processes:os.close(p)self._execute_external(cmd)os._exit(1) # 如果执行失败else:# 父进程processes.append(pid)prev_pipe = next_stdin if i > 0 else Noneexcept Exception as e:print(f"管道执行错误: {e}")return# 等待所有子进程完成for p in processes:os.waitpid(p, 0)def _handle_redirection(self, command):"""处理重定向命令"""args = shlex.split(command)stdin_file = Nonestdout_file = Nonecmd_args = []i = 0while i < len(args):if args[i] == ">":if i + 1 < len(args):stdout_file = args[i + 1]i += 2else:print("重定向错误: 缺少文件名")returnelif args[i] == "<":if i + 1 < len(args):stdin_file = args[i + 1]i += 2else:print("重定向错误: 缺少文件名")returnelse:cmd_args.append(args[i])i += 1if not cmd_args:print("重定向错误: 缺少命令")returntry:pid = os.fork()if pid == 0:# 子进程if stdin_file:try:fd = os.open(stdin_file, os.O_RDONLY)os.dup2(fd, 0)os.close(fd)except Exception as e:print(f"无法打开输入文件: {e}")os._exit(1)if stdout_file:try:fd = os.open(stdout_file, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o644)os.dup2(fd, 1)os.close(fd)except Exception as e:print(f"无法打开输出文件: {e}")os._exit(1)self._execute_external(" ".join(cmd_args))os._exit(1) # 如果执行失败else:# 父进程os.waitpid(pid, 0)except Exception as e:print(f"重定向执行错误: {e}")def _execute_external(self, command):"""执行外部命令"""args = shlex.split(command)if not args:returntry:# 处理环境变量替换processed_args = []for arg in args:if arg.startswith("$"):var_name = arg[1:]processed_args.append(self.env.get(var_name, ""))else:processed_args.append(arg)pid = os.fork()if pid == 0:# 子进程try:os.execvp(processed_args[0], processed_args)except FileNotFoundError:print(f"命令未找到: {processed_args[0]}")except Exception as e:print(f"执行错误: {e}")os._exit(1)else:# 父进程os.waitpid(pid, 0)except Exception as e:print(f"执行错误: {e}")def run(self):"""运行 Shell"""print("简易 Shell 已启动。输入 'exit' 退出。")while self.running:self.prompt()command = self.read_command()self.execute(command)if __name__ == "__main__":shell = SimpleShell()shell.run()
功能说明
这个简易 Shell 支持以下功能:
-
基本命令执行:
-
可以执行系统中的外部命令,如
ls
,pwd
,echo
等。
-
-
内置命令:
exit
:退出 Shellcd
:切换工作目录history
:显示命令历史
-
环境变量:
- 可以设置环境变量,如
FOO=bar
- 可以使用环境变量,如
echo $FOO
- 可以设置环境变量,如
-
管道:
-
支持使用
|
连接多个命令,如ls | grep py
-
-
重定向:
- 输出重定向:
ls > files.txt
- 输入重定向:
cat < files.txt
- 输出重定向:
-
信号处理:
- 忽略 Ctrl+C,不会终止 Shell
- 可以使用 Ctrl+D 或
exit
命令退出
使用方法
- 保存代码为
simple_shell.py
- 运行:
python simple_shell.py
- 在提示符下输入命令,如:
> ls > cd .. > echo $PATH > ls | grep py > cat > test.txt (输入一些文本,然后按 Ctrl+D) > cat test.txt
注意事项
- 这是一个简化的 Shell 实现,不支持复杂的 Shell 特性,如通配符、后台运行等
- 管道和重定向功能有一定限制,仅支持基本用法
- 错误处理相对简单,某些异常情况可能导致 Shell 行为异常
- 可以通过扩展代码来添加更多功能,如命令自动补全、作业控制等