java实现类linux shell效果

来源:互联网 发布:软件平台使用协议 编辑:程序博客网 时间:2024/06/08 02:02

一开始只是想要做一个网页版的linux shell,但是后来做着做着越来越觉得不太靠谱,于是乎,找了好久在国外网站上找到了一个相似的例子。

例子如下:

TestAppliaction.java

package dev.exec.tester;/** * <p>Title: ExecCommander</p> * <p>Description: This project serves as a launchpad for development and tests of a component to make use of process execution easier</p> * <p>Copyright: Copyright (c) 2003</p> * <p>Company: N/A</p> * @author Doron Barak * @version 1.0 */import java.awt.*;import javax.swing.*;public class TestApplication {private boolean packFrame = false;//Construct the applicationpublic TestApplication() {TestFrame frame = new TestFrame();//Validate frames that have preset sizes//Pack frames that have useful preferred size info, e.g. from their layoutif (packFrame) {frame.pack();} else {frame.validate();}//Center the windowDimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();Dimension frameSize = frame.getSize();if (frameSize.height > screenSize.height) {frameSize.height = screenSize.height;}if (frameSize.width > screenSize.width) {frameSize.width = screenSize.width;}frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);frame.setVisible(true);}//Main methodpublic static void main(String[] args) {try {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());} catch (Exception e) {e.printStackTrace();}new TestApplication();}}

TestFrame.java

package dev.exec.tester;/** * <p>Title: ExecCommander</p> * <p>Description: This project serves as a launchpad for development and tests of a component to make use of process execution easier</p> * <p>Copyright: Copyright (c) 2003</p> * <p>Company: N/A</p> * @author Doron Barak * @version 1.0 */import java.awt.*;import java.awt.event.*;import java.io.*;import javax.swing.*;import javax.swing.border.*;import dev.exec.util.*;public class TestFrame extends JFrame implements ExecProcessor {private JPanel contentPane;private JMenuBar jMenuBar1 = new JMenuBar();private JMenu jMenuFile = new JMenu();private JMenuItem jMenuFileExit = new JMenuItem();private JMenuItem jMenuHelpAbout = new JMenuItem();private JLabel statusBar = new JLabel();private BorderLayout borderLayout1 = new BorderLayout();private JTextField jTextField1 = new JTextField();private JMenuItem jMenuItem1 = new JMenuItem();private JTextArea jTextArea1 = new JTextArea();private JScrollPane jScrollPane1 = new JScrollPane();private ExecHelper exh;//Construct the framepublic TestFrame() {enableEvents(AWTEvent.WINDOW_EVENT_MASK);try {jbInit();} catch (Exception e) {e.printStackTrace();}}//Component initializationprivate void jbInit() throws Exception {contentPane = (JPanel)this.getContentPane();contentPane.setLayout(borderLayout1);this.setSize(new Dimension(400, 300));this.setTitle("Exec Test Frame");statusBar.setBorder(BorderFactory.createEtchedBorder());statusBar.setDebugGraphicsOptions(0);statusBar.setDoubleBuffered(true);statusBar.setOpaque(false);statusBar.setVerifyInputWhenFocusTarget(true);statusBar.setText(" Ready...");jMenuFile.setText("File");jMenuFileExit.setText("Exit");jMenuFileExit.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {jMenuFileExitActionPerformed(e);}});jTextField1.setBackground(UIManager.getColor("control"));jTextField1.setBorder(BorderFactory.createCompoundBorder(new TitledBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.white, Color.white, new Color(103, 101, 98), new Color(148, 145, 140)), "Input"), BorderFactory.createEmptyBorder( -2, 0, -2, 0)));jTextField1.setDoubleBuffered(true);jTextField1.setOpaque(false);jTextField1.setCaretColor(Color.black);jTextField1.setCaretPosition(0);jTextField1.setText("");jTextField1.addActionListener(new java.awt.event.ActionListener() {public void actionPerformed(ActionEvent e) {inputActionPerformed(e);}});contentPane.setBackground(UIManager.getColor("control"));contentPane.setDoubleBuffered(true);contentPane.setOpaque(true);jMenuItem1.setText("Run Command.exe");jMenuItem1.addActionListener(new java.awt.event.ActionListener() {public void actionPerformed(ActionEvent e) {runCommandActionPerformed(e);}});jTextArea1.setBackground(UIManager.getColor("control"));jScrollPane1.getViewport().setBackground(UIManager.getColor("control"));jScrollPane1.setAutoscrolls(true);jScrollPane1.setBorder(new TitledBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.white, Color.white, new Color(103, 101, 98), new Color(148, 145, 140)), "Output"));jScrollPane1.setOpaque(false);jTextArea1.setDoubleBuffered(true);jTextArea1.setOpaque(false);jTextArea1.setText("");jTextArea1.setColumns(80);jTextArea1.setRows(25);jTextArea1.setWrapStyleWord(true);jMenuFile.add(jMenuItem1);jMenuFile.add(jMenuFileExit);jMenuBar1.add(jMenuFile);setJMenuBar(jMenuBar1);contentPane.add(statusBar, BorderLayout.SOUTH);contentPane.add(jTextField1, BorderLayout.NORTH);contentPane.add(jScrollPane1, BorderLayout.CENTER);jScrollPane1.getViewport().add(jTextArea1, null);}private void updateTextArea(JTextArea textArea, String line) {textArea.append(line);textArea.setSelectionStart(textArea.getText().length());textArea.setSelectionEnd(textArea.getText().length());}//File | Exit action performedpublic void jMenuFileExitActionPerformed(ActionEvent e) {System.exit(0);}//Overridden so we can exit when window is closedprotected void processWindowEvent(WindowEvent e) {super.processWindowEvent(e);if (e.getID() == WindowEvent.WINDOW_CLOSING) {jMenuFileExitActionPerformed(null);}}public void processNewInput(String input) {updateTextArea(jTextArea1, input);}public void processNewError(String error) {updateTextArea(jTextArea1, error);}public void processEnded(int exitValue) {exh = null;statusBar.setText("Command.exe ended..");JOptionPane.showMessageDialog(this, "Exit value for Command.exe was [" + exitValue + "]", "Command.exe is done!", JOptionPane.INFORMATION_MESSAGE);try {Thread.sleep(1000);} catch (InterruptedException ex) {}jTextArea1.setText(null);statusBar.setText("Ready..");}void runCommandActionPerformed(ActionEvent e) {if (exh == null) {try {exh = ExecHelper.exec(this, "cmd.exe");statusBar.setText("Command.exe running..");} catch (IOException ex) {processNewError(ex.getMessage());}}}void inputActionPerformed(ActionEvent e) {if (exh != null) {exh.println(jTextField1.getText());jTextField1.setText(null);}}}

ExecHelper.java

package dev.exec.util;/** * <p>Title: ExecCommander</p> * <p>Description: This project serves as a launchpad for development and tests of a component to make use of process execution easier</p> * <p>Copyright: Copyright (c) 2003</p> * <p>Company: N/A</p> * @author Doron Barak * @version 1.0 */import java.io.*;public class ExecHelper implements Runnable {// Allocate 1K buffers for Input and Error Streams..private byte[] inBuffer = new byte[1024];private byte[] errBuffer = new byte[1024];// Declare internal variables we will need..private Process process;private InputStream pErrorStream;private InputStream pInputStream;private OutputStream pOutputStream;private PrintWriter outputWriter;private Thread processThread;private Thread inReadThread;private Thread errReadThread;private ExecProcessor handler;// Private constructor so that no one can create a new ExecHelper directly..private ExecHelper(ExecProcessor ep, Process p) {// Save variables..handler = ep;process = p;// Get the streams..pErrorStream = process.getErrorStream();pInputStream = process.getInputStream();pOutputStream = process.getOutputStream();// Create a PrintWriter on top of the output stream..outputWriter = new PrintWriter(pOutputStream, true);// Create the threads and start them..processThread = new Thread(this);inReadThread = new Thread(this);errReadThread = new Thread(this);// Start Threads..processThread.start();inReadThread.start();errReadThread.start();}private void processEnded(int exitValue) {// Handle process end..handler.processEnded(exitValue);}private void processNewInput(String input) {// Handle process new input..handler.processNewInput(input);}private void processNewError(String error) {// Handle process new error..handler.processNewError(error);}// Run the command and return the ExecHelper wrapper object..public static ExecHelper exec(ExecProcessor handler, String command) throws IOException {return new ExecHelper(handler, Runtime.getRuntime().exec(command));}// Print the output string through the print writer..public void print(String output) {outputWriter.print(output);}// Print the output string (and a CRLF pair) through the print writer..public void println(String output) {outputWriter.println(output);}public void run() {// Are we on the process Thread?if (processThread == Thread.currentThread()) {try {// This Thread just waits for the process to end and notifies the handler..processEnded(process.waitFor());} catch (InterruptedException ex) {ex.printStackTrace();}// Are we on the InputRead Thread?} else if (inReadThread == Thread.currentThread()) {try {// Read the InputStream in a loop until we find no more bytes to read..for (int i = 0; i > -1; i = pInputStream.read(inBuffer)) {// We have a new segment of input, so process it as a String..processNewInput(new String(inBuffer, 0, i));}} catch (IOException ex) {ex.printStackTrace();}// Are we on the ErrorRead Thread?} else if (errReadThread == Thread.currentThread()) {try {// Read the ErrorStream in a loop until we find no more bytes to read..for (int i = 0; i > -1; i = pErrorStream.read(errBuffer)) {// We have a new segment of error, so process it as a String..processNewError(new String(errBuffer, 0, i));}} catch (IOException ex) {ex.printStackTrace();}}}}

ExecProcessor.java

package dev.exec.util;/** * <p>Title: ExecCommander</p> * <p>Description: This project serves as a launchpad for development and tests of a component to make use of process execution easier</p> * <p>Copyright: Copyright (c) 2003</p> * <p>Company: N/A</p> * @author Doron Barak * @version 1.0 */public interface ExecProcessor {// This method gets called when the process sent us a new input String..public void processNewInput(String input);// This method gets called when the process sent us a new error String..public void processNewError(String error);// This method gets called when the process has ended..public void processEnded(int exitValue);}

以上代码是客户端的shell实现,亲自试了一下,适用于window系统,但是在linux中无法实现交互功能,自己在上面修修补补也还是实现不了,谁实现出来麻烦联系我哈。

其实抛开这个话题,Linux Shell的自动交互是可以通过某些操作来实现的。

以下内容引用其他网站,原地址:Linux Shell自动交互

/*reference start*/

你了解Linux系统么?你是Linux系统的应用者么?如果你要学习linux,你可能会遇到Linux Shell自动交互问题,这里将介绍Linux Shell自动交互的解决方法,在这里拿出来和大家分享一下。

一、背景

shell脚本在处理自动循环或大的任务方面可节省大量的时间,通过创建一个处理任务的命令清单,使用变量、条件、算术和循环等方法快速创建脚本以完成相应工作,这比在命令行下一个个敲入命令要省时省力得多。

但是有时候我们可能会需要实现和交互程序如ftp,telnet服务器等进行交互的功能,这时候我们需要用到shell的自动交互功能,本文收集了较常用的三种自动交互方法,并进行了比较和总结。

二、需求

需求1:
从一台Linux机器ftp登陆到另一台Linux机器,进行系列操作后关闭,懒得每次都手动输入密码。

需求2:
改变登录用户密码,懒得每次都输入新旧密码。

需求3:
希望su自动登录到root账户,懒得每次都输入root密码。

三、调试环境

终端:SecureCRT

系统:WinXP, CentOS 4.4(VmWare)

Shell:bash

注:shell有很多种,B类SHELL(sh, bash, ksh)之间行为相近;C类SHELL(csh, tcsh)之间行为相近,还有zsh和rc等shell,本文的调试环境是bash。

四、自动交互方法一

自动交互最关键的就是交互信息的自动输入,首先联想到文件重定向,在shell编程中有这样一种用法(参考Linux与UNIX SHELL编程指南 chapt 5.7):"command << delimiter  从标准输入中读入,直至遇到delimiter分界符。"

重定向操作符command << delimiter是一种非常有用的命令,shell将分界符delimiter之后直至下一个同样的分界符之前的所有内容都作为输入,遇到下一个分界符, shell就知道输入结束了。最常见的delimiter分界符是EOF,当然完全可以自定为其他字符。

对于需求1 要求的自动登陆ftp,并作系列操作,则可以用这种方法进行自动交互。代码如下:

  1. #!/bin/bash  
  2. ftp -i -n 192.168.167.187 << EOF 
  3. user hzc 123456  
  4. pwd  
  5. cd test  
  6. pwd  
  7. close  
  8. bye  
  9. EOF 

测试可以发现,如上代码使用帐号名hzc,密码123456成功登陆了ftp服务器,并进入目录,打印出了pwd。

五、自动交互方法二

需求2中要求采用非交互的方式改变登录用户密码,尝试用方法1,无法实现。

这时候联想到交互信息的另一个自动输入方法,管道,通过echo + sleep + | 可以实现这个需求。

  1. #!/bin/bash  
  2. (echo "curpassword"  
  3. sleep 1  
  4. echo "newpassword"   
  5. sleep 1  
  6. echo "newpassword")|passwd 

测试通过,运行这个脚本,直接把当前用户的curpassword改成newpassword。

六、自动交互方法三

需求3中要求自动登录root账号,尝试方法1和方法2,都出现错误提示standard in must be a tty。

这时候尝试寻找外部帮助,一个shell工具expect可以实现这个功能,其实expect就是一个专门用来实现自动交互功能的工具,expect的语法可以参考相关资料,代码如下:

  1. #!/usr/bin/expect  
  2. spawn su root  
  3. expect "password: "  
  4. send "123456\r"  
  5. expect eof  
  6. exit 

测试通过,运行这个脚本,直接从当前用户登录到root用户。

七、方法总结

方法一(重定向)简单直观,也经常有实际应用,但是在自动交互领域功能有限。

方法二(管道)也很简单直观,有时甚至不用sleep配合就能展现强大的自动交互实力,但是在某些时候也束手无策。

方法三(expect)在功能上是最为强大的,expect本来就是为实现自动交互功能而生,但是缺点是需要安装expect包,在嵌入式等环境下难以安装。

三个方法各有优劣,应用的好,都可以完成Linux Shell自动交互。

/*reference end*/


===========================================================================================================================


我自己研究了一下第三种,这种方法主要是使用一个工具expect,而expect又是建立在tcl之上的,所以要得先安装tcl才装expect。

以下内容引用其他网站,原地址:linux expect 安装

/*reference start*/

Expect是在Tcl基础上创建起来的,它还提供了一些Tcl所没有的命令,它可以用来做一些linux下无法做到交互的一些命令操作,在远程管 理方面发挥很大的作用。
spawn命令激活一个Unix程序来进行交互式的运行。 
send命令向进程发送字符串。
expect 命令等待进程的某些字符串。 
expect支持正规表达式并能同时等待多个字符串,并对每一个字符串执行不同的操作.


A. Tcl 安装
主页: http://www.tcl.tk
下载地址: http://www.tcl.tk/software/tcltk/downloadnow84.tml

1.下载源码包
wget http://nchc.dl.sourceforge.net/sourceforge/tcl/tcl8.4.11-src.tar.gz

2.解压缩源码包
tar xfvz tcl8.4.11-src.tar.gz

3.安装配置
cd tcl8.4.11/unix
./configure --prefix=/usr/tcl --enable-shared
make
make install

安装完毕以后,进入tcl源代码的根目录,把子目录unix下面的tclUnixPort.h copy到子目录generic中。
暂时不要删除tcl源代码,因为expect的安装过程还需要用。

B. expect 安装 (需Tcl的库)
主页: http://expect.nist.gov/

1.下载源码包
wget http://sourceforge.net/projects/expect/files/Expect/5.45/expect5.45.tar.gz/download

2.解压缩源码包
tar xzvf expect5.45.tar.gz

3.安装配置
cd expect5.45
./configure --prefix=/usr/expect --with-tcl=/usr/tcl/lib --with-tclinclude=../tcl8.4.11/generic

make
make install
ln -s /usr/tcl/bin/expect /usr/expect/bin/expect

/*reference end*/




0 0
原创粉丝点击