
Shell编程
shell 是作业系统的最外层。shell 合併程式语言以控制进程和档案,以及启动和控制其它程式。shell 通过提示您输入,向作业系统解释该输入,然后处理来自作业系统的任何结果输出来管理您与作业系统之间的互动。
基本介绍
- 外文名:shell
- 类别:作业系统
- 套用:编程技术
- 常见:在ARM技术里有很广的套用
基本概述
shell 提供了与作业系统通信的方式。此通信以互动的方式(来自键盘的输入立即操作)或作为一个 shell 脚本执行。shell 脚本是 shell 和作业系统命令的序列,它存储在档案中。
当登录到系统中时,系统定位要执行的 shell 的名称。在它执行之后,shell 显示一个命令提示符。普通用户的此提示符通常是一个 $(美元符)。当提示符下输入命令并按下 Enter 键时,shell 对命令进行求值,并尝试执行它。取决于命令说明,shell 将命令输出写到萤幕或重定向到输出。然后它返回命令提示符,并等待您输入另一个命令。
命令行是输入所在的行。它包含 shell 提示符。每行的基本格式如下:
$ 命令参数(一个或多个)
shell 视命令行的第一个字(直到第一个空白空格)为命令,所有后继字为自变数。
在Windows环境下,不论是使用Visual C++还是Delphi或是其他一些软体开发工具开发的应用程式,儘管存在着差别,但有一点是相同的:都是运行于Windows作业系统之下的。在程式开发过程中也经常要在自己的应用程式中加入一些Windows系统本身就有的功能,比如档案的拷贝、删除、查找以及运行程式等等。而这些功能在Windows作业系统下都是具备的,显然如果能直接从系统中调用这些功能将不仅仅减少程式的大小和开发人员的工作量,而且由于是直接通过作业系统来完成这些功能,将会大大减小这部分程式出现异常错误的机率。Windows系统虽说也存在不少错误,但常用功能的错误还是比较少的,而且通过补丁程式可以更低限度减少系统错误,因此程式设计师可以将调试检错的注意力放在应用程式的其他地方,对于调用系统功能这部分代码则可以不必投入太大的精力去调试,因为这部分调试的工作在作业系统发布的时候就已经由微软做好了。本文通过外壳编程,实现了搜寻档案、运行程式、控制工具条、最大最小化视窗的功能。
实现方法
前面所说的直接使用Windows作业系统部分功能的编程方法就是针对Windows作业系统外壳的编程,可以通过对作业系统提供的几个编程接口对作业系统的部分功能进行调用,甚至可以按照自己的意图在应用程式中对部分功能进行修改、扩展。但这方面的资料介绍不是特别多,讲的也大都语焉不详,而且用通常的编程方法去进行外壳编程是非常麻烦的,动辄就要对相关的结构对象进行设定,而这样的结构里的数据成员少则十来个多则几十个,因此配置起来非常烦琐,下面就以一个比较简单的外壳操作--拷贝档案进行举例说明:
…… SHFILEOPSTRUCT FileOp; //外壳的档案操作结构 FileOp.hwnd=m_hWnd; //设定句柄 //设定操作方式,拷贝用FO_COPY,删除用 FO_DELETE FileOp.wFunc=FO_COPY; FileOp.pFrom=m_source; //源档案路径 FileOp.pTo=m_detect; //目标档案路径 FileOp.fFlags=FOF_ALLOWUNDO; //允许恢复 FileOp.hNameMappings=NULL; FileOp.lpszProgressTitle=strTitle; //设定标题 SHFileOperation(&FileOp); //执行外壳拷贝 if(FileOp.fAnyOperationsAborted) //监测有无中止 TRACE("An Operation was aborted!!!\n"); …… |
上述代码实现起来虽然效果还是不错的,但然实现起来却是比较麻烦的,这仅仅是一个比较简单的外壳操作,对于一些比较複杂的外壳操作比如系统托盘、任务条等等的编程,更是尤为严重,而且象此类编程,MFC里并没有提供封装好的程式类库,提供的只有系统的WinAPI 应用程式接口,因此在程式开发过程中往往会有一种在进行SDK编程的感觉。
COM (Component Object Model,组件对象模型)是Microsoft创建的一种二进制和网路标準,也是Microsoft大力推广并已取得广泛认可的一种组件标準。在COM标準中,COM对象被很好的封装起来,客户无法访问对象的实现细节,提供给用户的唯一的访问途径是通过COM接口来访问。对于COM接口有两方面的含义:首先它是一组可供调用的函式,由此客户可以让该对象做某些事情;其次,也是更为重要的,接口是组件及其客户程式之间的协定。也就是说接口不但定义了可用什幺函式,也定义了当调用这些函式时对象要做什幺。Windows作业系统本身作为一个大的COM组件对象,也提供了一些必要的COM接口给客户程式,因此我们可以通过这些COM接口来直接对Windows外壳进行编程。
在程式进行正式编写设计之前有一点是肯定的:程式里需要用到COM接口,要对COM对象进行操作。因此首先要加入初始化COM和终止COM的代码。一般是在应用程式类的InitInstance()函式的开始处和返回前添加初始化COM和终止COM代码的:
…… CoInitialize(NULL); //初始化COM …… CoUninitialize(); //终止COM代码 …… |
以上两个函式在MFC程式和非MFC程式中都可以很好的使用。另外,如果程式框架是以MFC为基础的,那幺只需简单的调用AfxOleInit()函式就可以达到同样的目的。而且不必显式调用终止COM的代码。在COM标準中,访问COM对象的唯一途径是COM接口,因此在编写操纵Windows 系统外壳程式首先要得到其提供的COM接口。所用的COM接口是IShellDispatch,它是从IDispatch接口派生来的,在VC安装目录的VC98\Include\Exdisp.h头档案中有定义,下面节选了一些将要用到的接口定义:
…… EXTERN_C const IID IID_IShellDispatch; #if defined(__cplusplus) && !defined(CINTERFACE) interface DECLSPEC_UUID("D8F015C0-C278-11CE-A49E-444553540000") IShellDispatch : public Idispatch { public: …… virtual HRESULT STDMETHODCALLTYPE MinimizeAll( void) = 0; virtual HRESULT STDMETHODCALLTYPE UndoMinimizeALL( void) = 0; virtual HRESULT STDMETHODCALLTYPE FileRun( void) = 0; virtual HRESULT STDMETHODCALLTYPE CascadeWindows( void) = 0; virtual HRESULT STDMETHODCALLTYPE TileVertically( void) = 0; virtual HRESULT STDMETHODCALLTYPE TileHorizontally( void) = 0; virtual HRESULT STDMETHODCALLTYPE ShutdownWindows( void) = 0; virtual HRESULT STDMETHODCALLTYPE Suspend( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetTime( void) = 0; virtual HRESULT STDMETHODCALLTYPE TrayProperties( void) = 0; virtual HRESULT STDMETHODCALLTYPE Help( void) = 0; virtual HRESULT STDMETHODCALLTYPE FindFiles( void) = 0; virtual HRESULT STDMETHODCALLTYPE FindComputer( void) = 0; }; …… |
该接口在CoCreateInstance()函式创建COM对象时将会得到指向其的指针,通过这个函式客户程式可以避免显式同类厂打交道,其实该函式内部也调用了CoGetClassObject()函式来获取COM对象的类厂,只不过它把通过类厂创建对象的过程封装起来了,只需用户指定对象类的CLSID和待输出的接口指针及接口ID,显然这样直接创建COM对象是非常便捷的,在获取到COM对象指针之后就可以通过这个指针去访问调用COM对象里的方法来实现Windows 外壳的种种功能调用了。下面是实现该功能的部分关键代码:
…… HRESULT sc;//返回结果 IShellDispatch *pShellDisp = NULL; //初始化接口指针 //直接创建COM对象 sc = CoCreateInstance( CLSID_Shell,//指定待创建的COM对象标识符 NULL, //指定被聚合时的外部对象的接口指针 CLSCTX_SERVER, //指定组件类别,可以指定进程内组件进程外组件或者进程内控制对象。 IID_IDispatch, //指定接口ID,需要注意的是这里指的是待 //创建的COM对象的接口ID,而非类厂对象的接口标识符 (LPVOID *) &pShellDisp );//存放函式返回的对象的接口指针 /* 在上述代码中,CoCreateInstance首先调用CoGetClassObject函式创建类厂对象,然后用得到的类厂对象的接口指针创建真正的COM对象,最后把类厂对象释放并返回,这样就很好的把类厂禁止起来,使用户用起来更为简单。*/ if( FAILED(sc) )//必须用FAILED 或SUCCECCED来判断COM对象是否创建成功 return; pShellDisp->FindFiles(); //调用COM对象里的方法 pShellDisp->Release(); //释放申请到的接口指针 …… |
在这里通过pShellDisp接口指针调用了COM对象的FindFiles()方法去进行查找档案的系统外壳操作。同样,可以根据实际需要灵活调用回响的方法来执行相应的外壳操作,主要有以下几个方法:MinimizeAll:所有视窗最小化、UndoMinimizeALL:恢复视窗最小化、 FileRun:开始选单的"运行…"、CascadeWindows:层叠视窗、TileVertically:垂直平铺、TileHorizontally:水平平铺、ShutdownWindows:关闭Windows、Suspend 挂起计算机、SetTime:设定时间、TrayProperties:系统列属性、Help Windows:帮助、FindFiles:查找档案、FindComputer:查找计算机等。
这些接口均在VC安装目录的VC98\Include\Exdisp.h头档案中有定义,可以通过对该档案的查看来编写回响的外壳操作代码。
编程步骤
1、 启动Visual C++6.0,生成一个Win32应用程式,项目命名为"Shell";
2、 添加应用程式图示资源APP_ICON和对话框资源DLG_MAIN,对话框界面按上图一设计;
3、 使用Class Wizard为对话框上的各个按钮添加滑鼠单击处理函式;
4、 添加代码,编译运行程式。
常用技巧
1. 字元串的截取
shell字元串的截取的问题:
一、Linux shell 截取字元变数的前8位,有方法如下:
1) expr substr “$a” 1 8
2) echo $a|awk ‘{print substr(,1,8)}’
3) echo $a|cut -c1-8
4) expr $a : ‘\(.\\).*’
5) echo $a|dd bs=1 count=8 2>/dev/null
二、按指定的字元串截取
1) 第一种方法:
${varible##*string} 从左向右截取最后一个string后的字元串
${varible#*string}从左向右截取第一个string后的字元串
${varible%%string*}从右向左截取最后一个string后的字元串
${varible%string*}从右向左截取第一个string后的字元串
“*”只是一个通配符可以不要
例子:
$ MYVAR=foodforthought.jpg
$ echo ${MYVAR##*fo}
rthought.jpg
$ echo ${MYVAR#*fo}
odforthought.jpg
2) 第二种方法:${varible:n1:n2}:截取变数varible从n1到n2之间的字元串。
可以根据特定字元偏移和长度,使用另一种形式的变数扩展,来选择特定子字元串。试着在 bash 中输入以下行:
$ EXCLAIM=cowabunga
$ echo ${EXCLAIM:0:3}
cow
$ echo ${EXCLAIM:3:7}
abunga
这种形式的字元串截断非常简便,只需用冒号分开来指定起始字元和子字元串长度。
三、按照指定要求分割:
比如获取后缀名
ls -al | cut -d “.” -f2
2. 大小写转换
echo $uppercase |tr [A-Z] [a-z]
echo $lowercase |tr [a-z] [A-Z]
编程过程
///////////////////////////////////// #define INC_OLE2 #define WIN32_LEAN_AND_MEAN #define STRICT #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include <shlguid.h> #include <exdisp.h> #include “taskbar.h” #include “resource.h” // data static WNDPROC g_pfnOldProc; static HWND g_hwndButton=NULL; static HWND g_hDlg=NULL; static HINSTANCE g_hInstance; static HICON g_hIconLarge; static HICON g_hIconSmall; // functions static VOID OnRunPrograms( VOID ); static VOID OnFindFiles( VOID ); static VOID OnMinimizeAll( VOID ); static VOID OnUndoMinimize( VOID ); static VOID OnTaskbarProperties( VOID ); static VOID OnAddTab( HWND ); static VOID OnDeleteTab( VOID ); static VOID OnInitDialog( HWND ); static VOID OnButtonActivation( VOID ); // callbacks LRESULT CALLBACK APP_DlgProc( HWND, UINT, WPARAM, LPARAM ); LRESULT CALLBACK ButtonProc( HWND, UINT, WPARAM, LPARAM ); INT APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevious, LPSTR lpsz, INT iCmd ) { BOOL b; g_hIconLarge = (HICON) LoadImage( hInstance, “APP_ICON”, IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CXICON), 0 ); g_hIconSmall = (HICON) LoadImage( hInstance, “APP_ICON”, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CXSMICON), 0 ); // initialize OLE libraries CoInitialize(NULL); InitCommonControls(); // run main dialog g_hInstance = hInstance; b = DialogBox( hInstance, “DLG_MAIN”, NULL, (DLGPROC)APP_DlgProc ); // exit DestroyIcon( g_hIconLarge ); DestroyIcon( g_hIconSmall ); // free the objects used by ITaskbarList DestroyWindow( g_hwndButton ); OnDeleteTab(); CoUninitialize(); return b; }LRESULT CALLBACK APP_DlgProc( HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam ) { switch( uiMsg ) { case WM_INITDIALOG: OnInitDialog( hDlg ); break; case WM_COMMAND: switch( wParam ) { case IDC_FINDFILES: OnFindFiles(); return 1; case IDC_RUNPROGRAMS: OnRunPrograms(); return 1; case IDC_MINIMIZE: OnMinimizeAll(); return 1; case IDC_UNDOMINIMIZE: OnUndoMinimize(); return 1; case IDC_PROPERTIES: OnTaskbarProperties(); return 1; case IDC_ADDTAB: OnAddTab( hDlg ); return 1; case IDC_DELETETAB: OnDeleteTab(); return 1; case IDCANCEL: EndDialog( hDlg, FALSE ); return 0; } break; } return 0; } VOID OnFindFiles( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->FindFiles(); pShellDisp->Release(); return; } VOID OnTaskbarProperties( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER,IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->TrayProperties(); pShellDisp->Release(); return; } VOID OnRunPrograms( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IShellDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->FileRun(); pShellDisp->Release(); return; } VOID OnMinimizeAll( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->MinimizeAll(); pShellDisp->Release(); return; } VOID OnUndoMinimize( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->UndoMinimizeALL(); pShellDisp->Release(); return; } VOID OnInitDialog( HWND hDlg ) { // set the icons (T/F as to Large/Small icon) g_hDlg = hDlg; SendMessage( hDlg, WM_SETICON, FALSE, (LPARAM)g_hIconSmall ); SendMessage( hDlg, WM_SETICON, TRUE, (LPARAM)g_hIconLarge ); } VOID OnAddTab( HWND hWnd ) { static BOOL g_bFirstTime=TRUE; HRESULT sc; ITaskbarList *pDisp = NULL; sc = CoCreateInstance( CLSID_TaskbarList, NULL, CLSCTX_SERVER, IID_ITaskbarList, (LPVOID *) &pDisp ); if( FAILED(sc) ) return; // call the first time only if( g_bFirstTime ) { g_bFirstTime = FALSE; pDisp->HrInit(); // create a new button window g_hwndButton = CreateWindow( “button”, “My Button”, WS_CLIPSIBLINGS|BS_PUSHBUTTON,0, 0, 58, 14, hWnd, NULL, g_hInstance, NULL ); g_pfnOldProc = (WNDPROC) SubclassWindow( g_hwndButton, ButtonProc ); } pDisp->AddTab( g_hwndButton ); pDisp->Release(); return; } VOID OnDeleteTab( VOID ) { HRESULT sc; ITaskbarList *pDisp = NULL; sc = CoCreateInstance( CLSID_TaskbarList, NULL, CLSCTX_SERVER, IID_ITaskbarList, (LPVOID *) &pDisp ); if( FAILED(sc) ) return; pDisp->DeleteTab( g_hwndButton ); pDisp->Release(); return; } LRESULT CALLBACK ButtonProc( HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam ) { switch( uiMsg ) { case WM_NCACTIVATE: if( wParam==TRUE ) OnButtonActivation(); break; } return CallWindowProc( g_pfnOldProc, hwnd, uiMsg, wParam, lParam ); } VOID OnButtonActivation( VOID ) { HMENU hmenu; RECT r; LONG x, y; // get some window handles HWND h0=FindWindow(“Shell_TrayWnd”, NULL ); HWND h1=FindWindowEx(h0,NULL,”RebarWindow32″, NULL); HWND h2=FindWindowEx(h1,NULL,”MSTaskSwWClass”, NULL); HWND h3=FindWindowEx(h2,NULL,”SysTabControl32″, NULL); GetWindowRect( h3, &r ); // get the currently selected button and // create a new popup menu hmenu = CreatePopupMenu(); INT i=TabCtrl_GetCurSel( h3 ); if( i==-1 ) { AppendMenu( hmenu, MF_STRING, IDC_DELETETAB,”&Close” ); } else { AppendMenu( hmenu, MF_STRING, IDC_MINIMIZE,”&Minimize All” ); AppendMenu( hmenu, MF_STRING, IDC_UNDOMINIMIZE,”&Undo Minimize All” ); AppendMenu( hmenu, MF_SEPARATOR, 0, NULL ); AppendMenu( hmenu, MF_STRING, IDC_PROPERTIES,”&Taskbar Properties” ); } // set and immediately reset its size to get // the current width and height LONG l = TabCtrl_SetItemSize( h3, 0, 0 ); TabCtrl_SetItemSize( h3, LOWORD(l), HIWORD(l) ); // have the menu to appear just above the button if( i==-1 ) { POINT pt; GetCursorPos( &pt ); x = pt.x; y = pt.y; } else { x = r.left + LOWORD(l)*i+3; y = GetSystemMetrics(SM_CYSCREEN)-(HIWORD(l)+1); } TrackPopupMenu( hmenu, TPM_BOTTOMALIGN, x, y, 0, g_hDlg, 0); DestroyMenu( hmenu ); return; } |
课程大纲
第1章 简介及基础
shell简介及基础
- shell是什幺,为什幺要学习shell
- shell发展史及分类
- bash功能简介
- 部署设定bash环境
- shell脚本组成、运行模式及执行方法
- bash排错方法
- 父shell和子shell
- 常用快捷键
第2章 变数
- 变数分类
- 内部变数
- 预定义变数
- 自定义变数及基本用法
- 数组
- 特殊字元
- 别名
- Here Document
- 列印特殊字元
第3章 循环结构与流程控制
- if条件判断
- case条件判断
- for循环
- while循环
- until循环
- select命令
- break和continue
第4章 函式
- 函式用法
- 函式作用範围
- 参数使用
- 建立函式馆
- 递归函式
第5章 算术运算
- 算术式简介
- 算术扩展
- 利用expr做算术运算
- 使用$[]做算术运算
- 使用内置变数declare、let做算术运算
- 利用bc做浮点运算
- 进制转换
第6章 重定向与转向
- 档案代码
- 操作档案
- 输入输出转向
- 转向附加
- 标準错误伴随输出转向
- Here Document转向
第7章 高级变数与字元串操作
- 变数扩展:测试存在性及空值
- 变数扩展:取字元串切片,字元串长度
- 变数扩展:对比样式
- 变数扩展:取变数名称列表,数组索引列表
- 命令替换
第8章 正则表达式
- 入门介绍
- 元字元
- 字条转义
- 重複
- 字元类
- 分支条件
- 反义
- 分组
- 后向引用
- 零宽断言与负向零宽断言
- 贪婪与懒惰
- 注释
- 处理选项
- 平衡组/递归匹配
第9章 sed编辑器
- sed介绍
- sed基本语法
- sed调用方式
- sed高级用法
第10章 awk学习
- awk原理介绍
- awk基本语法
- awk调用方式
- awk循环语句
- awk函式
- awk数组
- awk的BEGIN和END模式
- awk数学运算和字元串操作
- awk重定向输出
- awk与bash之间传参调用
- awk调试方法
第11章 文字与图形接口编程
- dialog文本接口编程
- xdialog图形接口编程
第12章 bash网路编程
- bash网路转向
- 远程执行命令
- expect与自动登录
第13章 trap陷阱触发
- 信号signal
- trap运用
第14章 shell脚本加密与包装
- 加密shell脚本
- 生成二进制执行档
第15章 shell中常用命令介绍
- grep命令详解
- find与xargs
- sort和uniq命令详解
- cut命令详解
- curl与wget命令详解
- cat、tac与rev
- tr命令详解
- paste命令详解
- join命令详解
第16章 一些shell技巧
- 利用脚本修改密码
- 判断奇偶
- 添加行号与删除行号
- 删除行首空格,删除重複行
- 合併行操作
- 逐行读取操作
- 字元与ASCII码转换操作
- 连线mysql资料库操作
第17章 shell十三问
- PS1和CR的关係
- echo知多少
- “”(双绰号)与”(单引号)差在哪儿
- export前后差在哪儿
- exec跟source差在哪儿
- ()与{}差在哪儿
- $(())和$()、${}差在哪儿
- $@和$*差在哪儿
- &&和||差在哪儿
- >和<差在哪儿
- 你要if还是case
- for what?while和until差在哪儿?
- [^ ]和[! ]差在哪儿
第18章 综合实战讲解一
- 系统信息收集脚本
- 备份脚本
- 日誌切割脚本
- nagios监控外挂程式脚本
- 发邮件脚本
第19章 综合实战讲解二
- 系统初始化脚本
- 基础软体安装脚本
- iptables脚本
- 线上操作记录审核脚本
- 文本完整性审核脚本
- kickstart配置脚本