mini shell 的想法是通过python实现一个类似与linux的shell。目前只支持4条命令 ls,cat,cd,history。(如果exit也算一条命令的话,那就是五条)。
功能也类似与linux的shell,比如说运行这个python的程序之后,输入ls,它会返回当前目录的文件和文件夹。
通过这个小demo:
- 可以熟悉一个python下面os库的一些函数,比如说如何获取当前工作目录,主机名,用户名等等。
- 熟悉signal信号机制,比如我们在linux下面输入ctrl+c 是挂起信号,但是你在mini shell里面要屏蔽这个信号,因为并不希望ctrl+c就退出当前的minishell。
- 了解一下shell,在学习linux的时候,其实对shell刚接触的时候,会有很大的恐惧感。其实我们在shell下输入的命令,比如cat,ls 他们的本质都是可执行文件,位于系统的bin目录下面。
输入ls -l,就好像我们现在有一个可执行文件叫 a.out,
//-l 相当于是参数,通过mian的argv获得
./a.out -l
ls和自己写得a.out 的区别在于,a.out必须在当前目录下才可以执行,但是ls可以在任何目录。你可以更改环境变量,把a.out的当前目录,加入到环境变量里面,这样就可以了。(这也就是我们安装java,python,mysql 等为什么要配置环境变量的原因了)
前面可以参考:
Python 在linux下获得当前工作目录,主机名,用户名,操作系统平台等信息http://www.jianshu.com/p/5c294b5bc7b9
运行结果:
这是一个未完工的版本:
history的命令,exit命令还没有实现,也没有写成一个循环。有空来更新。实验是参考实验楼的一个python教程。
解释器的版本是python2.7,换成3也没有问题,稍微改一下print函数就可以。
#coding:utf-8
import os
import sys
import shlex
import getpass
import socket
import signal
import subprocess
import platform
import re
SHELL_STATUS_STOP = 0
SHELL_STATUS_RUN = 1
# 使用 os.path.expanduser('~') 获取当前操作系统平台的当前用户根目录
HISTORY_PATH = os.path.expanduser('~') + os.sep + '.shiyanlou_shell_history'
def ls(args):
if len(args)>0:
print os.getcwd()
def cd(args):
if len(args) > 0:
os.chdir(args[0])
else:
os.chdir(os.getenv('HOME'))
print os.getcwd()
return SHELL_STATUS_RUN
def getenv(args):
#print 'test : ',args
if len(args) >0:
print(os.getenv(args))
def exit():
#TO-DO
print ('exit')
def history():
#TO-DO
print ('history')
def cat(arg):
#TO-DO
print ('cat')
def display_cmd_prompt():
user=getpass.getuser()
hostname=socket.gethostname()
cwd=os.getcwd()
base_dir=os.path.basename(cwd)
home_dir=os.path.expanduser('~')
if cwd==home_dir:
base_dir='~'
#sys.stdout.write("[%s@%s %s]$ " % (user, hostname, base_dir))
#改變顏色
sys.stdout.write("[\033[1;33m%s\033[0;0m@%s \033[1;36m%s\033[0;0m] $ " % (user, hostname, base_dir))
sys.stdout.flush()
#這部分使用啦正則表達式來處理
def getsplit(str):
# 其实就是按空格符将命令与参数分开
# 比如,'ls -l /home/shiyanlou' 划分之后就是
# ['ls', '-l', '/home/shiyanlou']
#res=re.split(r'\s',str)
res=re.split(r'\s+',str)
return res
def isgetenv(tokens):
token=tokens[0]
#print token
if token.startswith('$'):
getenv(token[1:])
#print os.getenv(token[1:])
return True
else:
return False
#構建一個字典 字典裏面的value,指的是函數,比如cd是cd函數
built_in_cmds = {}
built_in_cmds['cd']=cd
built_in_cmds['ls']=ls
built_in_cmds['cat']=cat
built_in_cmds['exit']=exit
built_in_cmds['history']=history
#to-do 這裏應該寫成一個循環
#輸出
display_cmd_prompt()
#等待輸入
cmd=sys.stdin.readline()
#切分
cmd_tokens=getsplit(cmd)
#cmd_tokens=[ls -l]
#cmd_tokens=preprocess(cmd_tokens)
if isgetenv(cmd_tokens)==False:
#print cmd_tokens[0]
#print cmd_tokens[1]
cmd_args=cmd_tokens[1:]
#print cmd_args
if cmd_tokens[0] in built_in_cmds:
#print cmd_args
built_in_cmds[cmd_tokens[0]](cmd_args)