当前位置: 首页 > java >正文

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 支持以下功能:

  • 基本命令执行

    • 可以执行系统中的外部命令,如 lspwdecho 等。

  • 内置命令

    • exit:退出 Shell
    • cd:切换工作目录
    • 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 行为异常
  • 可以通过扩展代码来添加更多功能,如命令自动补全、作业控制等
http://www.xdnf.cn/news/7314.html

相关文章:

  • Python的传参过程的小细节
  • 什么是5G前传、中传、回传?
  • 数据分析—Excel数据清洗函数
  • Compose Kotlin Multiplatform跨平台基础运行
  • CM0启动CM7_0、CM7_1注意事项
  • PCB设计教程【入门篇】——电路分析基础-基本元件(电阻电容电感)
  • Docker 入门指南:从安装配置到核心概念解析
  • [ 计算机网络 ] | 宏观谈谈计算机网络
  • 十三、Hive 行列转换
  • 计算机视觉与深度学习 | Python实现ARIMA-WOA-CNN-LSTM时间序列预测(完整源码和数据
  • netcore项目使用winforms与blazor结合来开发如何按F12,可以调出chrome devtool工具辅助开发
  • 通过低功耗蓝牙通信实例讲透 MCU 各个定时器
  • AT 指令详解:基于 MCU 的通信控制实战指南AT 指令详解
  • ESP32开发-两个WIFI设备的通讯搭建
  • AI大模型从0到1记录学习numpy pandas day25
  • 无人设备遥控器之数据压缩与编码技术篇
  • PLC组网的方法、要点及实施全解析
  • android13以太网静态ip不断断开连上问题
  • C++(24):容器类<list>
  • Unreal 从入门到精通之SceneCaptureComponent2D实现UI层3D物体360°预览
  • MAC常用操作整理
  • MAC电脑中右键后复制和拷贝的区别
  • C++:与7无关的数
  • 基于 Vue 和 Node.js 实现图片上传功能:从前端到后端的完整实践
  • 汽车零部件的EMI抗扰性测试
  • Java中的流详解
  • vue3 vite 路由
  • 容器化-K8s-镜像仓库使用和应用
  • Ubuntu Desktop QEMU/KVM中使用Ubuntu Server 22.04配置k8s集群
  • k8s1.27集群部署mysql8.0双主双从