转载

如何在代码里调用执行命令行(有可能持续更新)

在电脑上可以打开 cmd/powershell/iTerm2/Git Bash 进行命令行的操作,但是如何用其他语言比如 Python/Java 执行命令行呢?

这么做当然不是闲的蛋疼,而是有些工作的确依赖这样的实现。

Java/Kotlin

Java 和 Kotlin 本质上都是运行在 jvm 虚拟机上,都是调用 Runtime 接口提供的方法。以下以 Java为例。

public class CmdShell {
    public static void main(String[] args) {
        run();
    }

    private static void run() {
        String os = System.getProperty("os.name").toLowerCase();
        System.out.println(os);
        if (os.toLowerCase().contains("mac")) {
            runOnMac("ls");
            runOnMac("ls -hl");
            runOnMac("adb devices");
        } else if (os.contains("windows")) {
            runOnWindows("dir");
            runOnWindows("git log");
        }
    }

    private static void runOnWindows(String cmd) {
        Runtime runtime = Runtime.getRuntime();
        String realCmd = "cmd /c " + cmd;
        try {
            Process p = runtime.exec(realCmd);
            String result = StreamUtil.StreamToStringWithReader(p.getInputStream());
            String output = String.format("execute cmd : %s and result is /n/n%s ", cmd, result);
            System.out.println(output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void runOnMac(String cmd) {
        Runtime runtime = Runtime.getRuntime();
        try {
            Process p = runtime.exec(cmd);
            String result = StreamUtil.StreamToStringWithReader(p.getInputStream());
            String output = String.format("execute cmd : /" %s /" and result is /n/n%s ", cmd, result);
            System.out.println(output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

需要注意的是

  • Mac Os X 和 Windows 上对命令行执行机制有些区别,因此需要按平台做一下区分
  • exec 有一系列的重构方法可以调用
如何在代码里调用执行命令行(有可能持续更新)

Android

Android 应用层的实现,本质上还是 Java 或 Kotlin,因此代码实现基本和上面:point_up_2:一致。但是本质上执行命令的还是内核,因此需要执行某些命令是需要权限的,具体权限可能和厂商对 ROM 的实现有关。一些比较有用的命令还是可以执行的比如, pwd,ifconfig,ping ,但是 ls 命令是需要权限的(估计 root 之后的手机是可以的,2019 年想 root 一个手机忽然发现已经很难了 :cry:)。借助 ping 命令可以做网络相关的一些事情。

如何在代码里调用执行命令行(有可能持续更新) 如何在代码里调用执行命令行(有可能持续更新)

Python

import os
def os_open():
    """
    popen方法通过p.read()获取终端输出,而且popen需要关闭close().
    当执行成功时,close()不返回任何值,失败时,close()返回系统返回值..
    可见它获取返回值的方式和os.system不同
    强调的一点是,不支持参数,不支持管道
    :return:
    """
    out = os.popen("dir")
    print(out.read())
    out.close()

popen返回的是一个file对象,跟open打开文件一样操作了,r是以读的方式打开. 用 python 执行命令行,最有意思的实现莫过于之前很火爆的微信小程序游戏《跳一跳》的 刷分程序 。就是通过分析图片计算位置,然后在程序内调用 adb shell swipe x,y 命令实现的

gralde

这里的 gradle 指工程构建过程的 build.gralde 或 customXXX.gradle 脚本文件。在这些脚本文件中,其实也是可以执行命令行的。

def getGitBranch() {
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine "git"
        args "rev-parse", "--abbrev-ref", "HEAD"
        standardOutput = stdout
    }
    return stdout.toString().trim()
}

ext {
    getGitBranch = this.&getGitBranch
}

这样就可以使用 gitGitBranch 方法获取当前工程的 git 分支了。可以看到 最核心的实现,就是把要执行的命令写到 exec 的闭包当中,然后用一个 OutputStream 的装饰器接收一下输出就可以了 。当然,如果你要执行的命令,不关注结果,输出就可以忽略了。

groovy

我们知道 groovy 编译后的字节码也是在 JVM 虚拟机上执行。只是他作为一种动态类型的语言,使用起来比较灵活。在 groovy 中执行命令行和 gradle 非常相似.

class GitTool {
     static String getGitBranch(Project project) {
        def out = new ByteArrayOutputStream()
        project.exec {
            it.commandLine("git")
            it.args("rev-parse", "--short", "HEAD")
            it.standardOutput = out
        }
        return out.toString().trim()
    }
}

你可以理解为把闭包的实现给展开了。

JavaScript

关于 JavaScript 这里简单讨论一下之前自己使用 Node 时的场景。浏览器内是如何一番场景,不太了解不做分析。

function run_cmd(cmd, args, callBack ) {
    var spawn = require('child_process').spawn;
    var child = spawn(cmd, args);
    var resp = "";

    child.stdout.on('data', function (buffer) { resp += buffer.toString() });
    child.stdout.on('end', function() { callBack (resp) });
}

run_cmd( "ls", ["-l"], function(text) { console.log (text) });

run_cmd 方法定义了具体实现,后续使用此方法即可。

…… may be continued

原文  https://rebooters.github.io/2019/12/08/如何调用命令行/
正文到此结束
Loading...