php 通过shell_exec调用jar_shell脚本执行jar包 exec - CSDN
精华内容
参与话题
  • PHP 调用 exec 执行中文命令的坑

    千次阅读 2017-06-25 09:21:08
    首先,我们的项目中有这么一个需求,就是需要在发送请求时,需要调用 java 写的一个加密库。所以不可避免的会使用到 phpexec 方法执行 shell 命令。 一切都很正常,直到,出现了中文。哎。具体的 case 如下...
    首先,我们的项目中有这么一个需求,就是需要在发送请求时,需要调用 java 写的一个加密库。所以不可避免的会使用到 php 的 exec 方法执行 shell 命令。

    一切都很正常,直到,出现了中文。哎。具体的 case 如下:

    样例代码:

    <?php
        $cmd = 'java -jar sign-maker.jar mike messi';
        exec($cmd, $ret, $out);
        var_dump($ret);
        $cmd = 'java -jar sign-maker.jar 麦克 梅西';
        exec($cmd, $ret, $out);
        var_dump($ret);
    其中,sign-maker.jar 就是我们按照第三方的加密协议的一个签名包(虽然也是我写的),执行这段代码,我们可以得到如下的结果:

    php index.
    php
    array(1)
    {
      [0]=>
      string(80) "495cc9e9269265cc0e7d58940367976571a1c4fdb90bf842ee4ba703fb1a554abf0772218e29d3d8"
    }
    array(2) {
      [0]=>
      string(80) "495cc9e9269265cc0e7d58940367976571a1c4fdb90bf842ee4ba703fb1a554abf0772218e29d3d8"
      [1]=>
      string(80) "e442a87d369a1a3c610bb2d18bd38fdad3b52644ab0ef86a21b57a5d0d75cb8dbf0772218e29d3d8"
    }
    可以看到,我们已经生成了两个 sign 值。但是,在传输过程中,对面居然报了 sign 无效的错误。觉得很奇怪,第一个 sign 是正确的,但是第二个就是败了。于是我们在终端中手动输入了这个命令:

    └─[$]> java -jar sign-maker.jar 麦克 梅西
    92144a18e9f75ec2e257c9bb15a05825a706064445b9492efd065dfd6c8b38d0bf0772218e29d3d8
    发现 sign 果然不同。所以第一反应是字符编码的问题,尝试了 utf8encode,iconv 等等方法转换字符,但是都是无功而返。最后定为到环境变量的问题上。

    解决办法

    解决办法先上,在 exec 的命令前首先指定字符集:

    <?php
        $set_charset = 'export LANG=en_US.UTF-8;';
        $cmd = 'java -jar sign-maker.jar mike messi';
        exec($set_charset.$cmd, $ret, $out); 
        var_dump($ret);
    这样即可。
    展开全文
  • 但是我想在一个安卓应用上(比如一个按钮隐藏当前应用后运行)调用adb shell uiautomator runtest ...命令。 运行: Runtime.getRuntime().exec("am start -n com.tencent.mm/com.tencent.mm.ui.LauncherUI") ...
  • phpexec()函数返回值

    万次阅读 2017-06-08 16:23:31
    php中可以使用 exec() 函数调用外部函数。 语法: string exec ( string $command [, array &$output [, int &$return_var ]] ) 其中$output内容会追加,要注意

    php中可以使用 exec() 函数调用外部函数。


    语法:

    string exec ( string $command [, array &$output [, int &$return_var ]] )

    exec() 会执行command参数所指定的命令。

    exec() 默认情况会返回指定命令结果的最后一行,指定output参数,会使用返回结果填充output如果output参数中已经有元素,exec()会在output后面追加

    return_var 会command执行结果的返回码,正常返回值为0。


    自己踩了一个坑,就是忘记exec()会在output后面追加。

    例子:

    <?php
    var_dump(exec("date;ls", $res));
    var_dump($res);
    var_dump(exec("date;ls", $res));
    var_dump($res);
    
    

    测试目录下有三个文件,fileA fileB test.php,执行的结果如下:


    展开全文
  • Dockerfile中的ENTRYPOINT指令和CMD指令都可以设置容器启动时要执行的命令,但用途是有略微不同的。 ENTRYPOINT指令和CMD指令虽然是在Dockerfile中定义,但是在构建镜像的时候并不会被执行,只有在执行docker run...

    Dockerfile中的ENTRYPOINT指令和CMD指令都可以设置容器启动时要执行的命令,但用途是有略微不同的。

    ENTRYPOINT指令和CMD指令虽然是在Dockerfile中定义,但是在构建镜像的时候并不会被执行,只有在执行docker run命令启动容器时才会起作用。

    在Dockerfile中,只能有一个ENTRYPOINT指令,如果有多个ENTRYPOINT指令则以最后一个为准。

    在Dockerfile中,只能有一个CMD指令,如果有多个CMD指令则以最后一个为准。

    在Dockerfile中,ENTRYPOINT指令或CMD指令,至少必有其一。

    1. ENTRYPOINT指令

    首先,执行docker run如果带有其他命令参数,不会覆盖ENTRYPOINT指令。

    不过,docker run的--entrypoint可以覆盖Dockerfile中ENTRYPOINT设置的命令,后续文章详述。

    1) exec格式用法(推荐)

    ENTRYPOINT ["top","-b", "-H"]

    exec格式,也被称为JSON风格["command","arg1"]。

    在创建容器实例执行docker run命令时,设置的任何命令参数或CMD指令的命令,都将作为ENTRYPOINT指令的命令参数,追加到ENTRYPOINT指令的命令之后。

    如,在Dockerfile中有如上ENTRYPOINT指令的情况下,执行docker run <container_name> -v启动容器。则容器启动后执行的第一条完整命令如下:

    top -b -H -v

    即将-v作为top的追加参数。

    2) shell格式用法

    ENTRYPOINT top -b -H

    这种格式屏蔽追加任何参数,即CMD指令或docker run ... <command>的参数都将被忽略。

    采用shell格式,在创建容器后会首先调用Shell,即自动在命令前面追加/bin/sh -c。如,对于上述定义,在容器启动时执行的第一条命令如下:

    /bin/sh -c top -b -H

    这样,ENTRYPOINT指令设置的top命令就不是容器中的第一个进程PID 1,这样在容器停止的时候就无法收到系统的SIGTERM信号。要想收到SIGTERM信号,务必使用Bash的内置exec命令使得top的PID 1,定义ENTRYPOINT指令如下:

    ENTRYPOINT exec top -b -H

    2. CMD指令

    首先,执行docker run如果带有其他命令参数,将会覆盖CMD指令。

    如果在Dockerfile中,还有ENTRYPOINT指令,则CMD指令中的命令将作为ENTRYPOINT指令中的命令的参数(CMD和ENTRYPOINT指令必须采用JSON风格,即exec格式,定义)。

    1) exec格式用法(推荐)

    CMD ["echo","hello", "world"]

    exec格式,也被称为JSON风格["command","arg1"]。

    这种格式,在容器执行时不会调用任何Shell,即不会进行命令中的变量替换。要进行Shell处理,需要将sh直接加入到命令中:

    CMD ["sh", "-c", "echo $HOME"]

    这样,$HOME才会被解析为真实的主目录。

    但是并不推荐将sh加入到CMD指令中,因为CMD指令的命令往往作为ENTRYPOINT指令的追加参数,因而如下形式更常见:

    CMD ["-c","echo world"]

    2) shell格式用法

    CMD echo $HW

    这种格式,在创建容器后会首先调用Shell,即自动在命令前面追加/bin/sh -c,即上述设置将执行如下命令:

    /bin/sh -c echo $HW

    3. 比较ENTRYPOINT与CMD指令

    ENTRYPOINT指令,往往用于设置容器启动后的第一个命令,这对一个容器来说往往是固定的。
    CMD指令,往往用于设置容器启动的第一个命令的默认参数,这对一个容器来说可以是变化的。
    docker run <command>往往用于给出替换CMD的临时参数

    ENTRYPOINT&CMD
    CMD\ENTRYPOINT N/A ENTRYPOINT exec_entry p1_entry ENTRYPOINT [“exec_entry”, “p1_entry”]
    N/A Error /bin/sh -c exec_entry p1_entry exec_entry p1_entry
    CMD [“exec_cmd”, “p1_cmd”] exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry exec_cmd p1_cmd
    CMD [“p1_cmd”, “p2_cmd”] p1_cmd p2_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry p1_cmd p2_cmd
    CMD exec_cmd p1_cmd /bin/sh -c exec_cmd p1_cmd /bin/sh -c exec_entry p1_entry exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

     

    参考链接:

    https://docs.docker.com/engine/reference/builder/

    展开全文
  • 摘要: 该文章来自阿里巴巴技术协会(ATA)精选集 背景 我们在开发过程中,大部分是java开发, 而在文本处理过程中,主要就是脚本进行开发。 java开发的特点就是我们可以很早地进行TDDL, METAQ 等等地对接;...

    摘要: 该文章来自阿里巴巴技术协会(ATA)精选集 背景 我们在开发过程中,大部分是java开发, 而在文本处理过程中,主要就是脚本进行开发。 java开发的特点就是我们可以很早地进行TDDL, METAQ 等等地对接; 而脚本开发的特点就是在进行批处理的时候非常方便。

    背景

    我们在开发过程中,大部分是java开发, 而在文本处理过程中,主要就是脚本进行开发。 java开发的特点就是我们可以很早地进行TDDL, METAQ 等等地对接; 而脚本开发的特点就是在进行批处理的时候非常方便。 前阵子我遇到这么一个需求场景: 对抓取的数据进行打包, 后来又遇到我要通过脚本进行抓取,比如nodejs下基于phantomjs的casperjs爬虫。

    解决方法

    对于第一个问题:java抓取,并且把结果打包。 
    那么比较直接的做法就是,java接收各种消息(db,metaq等等),然后借助于jstorm集群进行调度和抓取。 最后把抓取的结果保存到一个文件中,并且通过调用shell打包, 回传。 也许有同学会问, 为什么不直接把java调用odps直接保存文件,答案是,我们的集群不是hz集群,直接上传odps速度很有问题,因此先打包比较合适。(这里不纠结设计了,我们回到正题)

    java调用shell的方法

    通过ProcessBuilder进行调度

    这种方法比较直观,而且参数的设置也比较方便, 比如我在实践中的代码(我隐藏了部分业务代码):

    ProcessBuilder pb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, param1,
                                                   param2, param3);
            pb.directory(new File(SHELL_FILE_DIR));
            int runningStatus = 0;
            String s = null;
            try {
                Process p = pb.start();
                try {
                    runningStatus = p.waitFor();
                } catch (InterruptedException e) {
                }
    
            } catch (IOException e) {
            }
            if (runningStatus != 0) {
            }
            return;
    

    这里有必要解释一下几个参数:
    RUNNING_SHELL_FILE:要运行的脚本
    SHELL_FILE_DIR:要运行的脚本所在的目录; 当然你也可以把要运行的脚本写成全路径。
    runningStatus:运行状态,0标识正常。 详细可以看java文档。
    param1, param2, param3:可以在RUNNING_SHELL_FILE脚本中直接通过1,2,$3分别拿到的参数。

    直接通过系统Runtime执行shell

    这个方法比较暴力,也比较常用, 代码如下:

    p = Runtime.getRuntime().exec(SHELL_FILE_DIR + RUNNING_SHELL_FILE + " "+param1+" "+param2+" "+param3);
    p.waitFor();
    

    我们发现,通过Runtime的方式并没有builder那么方便,特别是参数方面,必须自己加空格分开,因为exec会把整个字符串作为shell运行。

    可能存在的问题以及解决方法

    如果你觉得通过上面就能满足你的需求,那么可能是要碰壁了。你会遇到以下情况。

    没权限运行

    这个情况我们团队的朱东方就遇到了, 在做DTS迁移的过程中,要执行包里面的shell脚本, 解压出来了之后,发现执行不了。 那么就按照上面的方法授权吧

    ProcessBuilder builder = new ProcessBuilder("/bin/chmod", "755", tempFile.getPath());
                Process process = builder.start();
                int rc = process.waitFor();
    

    java进行一直等待shell返回

    这个问题估计更加经常遇到。 原因是, shell脚本中有echo或者print输出, 导致缓冲区被用完了! 为了避免这种情况, 一定要把缓冲区读一下, 好处就是,可以对shell的具体运行状态进行log出来。 比如上面我的例子中我会变成:

    ProcessBuilder pb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, keyword.trim(),
                                                   taskId.toString(), fileName);
            pb.directory(new File(CASPERJS_FILE_DIR));
            int runningStatus = 0;
            String s = null;
            try {
                Process p = pb.start();
                BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
                BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                while ((s = stdInput.readLine()) != null) {
                    LOG.error(s);
                }
                while ((s = stdError.readLine()) != null) {
                    LOG.error(s);
                }
                try {
                    runningStatus = p.waitFor();
                } catch (InterruptedException e) {
                }
    
    

    记得在start()之后, waitFor()之前把缓冲区读出来打log, 就可以看到你的shell为什么会没有按照预期运行。 这个还有一个好处是,可以读shell里面输出的结果, 方便java代码进一步操作。

    也许你还会遇到这个问题,明明手工可以运行的命令,java调用的shell中某一些命令居然不能执行,报错:命令不存在!

    比如我在使用casperjs的时候,手工去执行shell明明是可以执行的,但是java调用的时候,发现总是出错。 通过读取缓冲区就能发现错误日志了。 我发现即便自己把安装的casperjs的bin已经加入了path中(/etc/profile, 各种bashrc中)还不够。 比如:

    export NODE_HOME="/home/admin/node"
    export CASPERJS_HOME="/home/admin/casperjs"
    export PHANTOMJS_HOME="/home/admin/phantomjs"
    export PATH=$PATH:$JAVA_HOME/bin:/root/bin:$NODE_HOME/bin:$CASPERJS_HOME/bin:$PHANTOMJS_HOME/bin
    
    

    原来是因为java在调用shell的时候,默认用的是系统的/bin/下的指令。特别是你用root权限运行的时候。 这时候,你要在/bin下加软链了。针对我上面的例子,就要在/bin下加软链:

    ln -s /home/admin/casperjs/bin/casperjs casperjs;
    ln -s /home/admin/node/bin/node node;
    ln -s /home/admin/phantomjs/bin/phantomjs phantomjs;
    

    这样,问题就可以解决了。

    如果是通过java调用shell进行打包,那么要注意路径的问题了

    因为shell里面tar的压缩和解压可不能直接写:

    tar -zcf /home/admin/data/result.tar.gz /home/admin/data/result

    直接给你报错,因为tar的压缩源必须到路径下面, 因此可以写成

    tar -zcf /home/admin/data/result.tar.gz -C /home/admin/data/ result

    如果我的shell是在jar包中怎么办?

    答案是:解压出来。再按照上面指示进行操作。
    (1)找到路径

    String jarPath = findClassJarPath(ClassLoaderUtil.class);
            JarFile topLevelJarFile = null;
            try {
                topLevelJarFile = new JarFile(jarPath);
                Enumeration<JarEntry> entries = topLevelJarFile.entries();
                while (entries.hasMoreElements()) {
                    JarEntry entry = entries.nextElement();
                    if (!entry.isDirectory() && entry.getName().endsWith(".sh")) {
                        对你的shell文件进行处理
                    }
                }
    

    对文件处理的方法就简单了,直接touch一个临时文件,然后把数据流写入,代码:

    FileUtils.touch(tempjline);
    tempjline.deleteOnExit();
    FileOutputStream fos = new FileOutputStream(tempjline);
    IOUtils.copy(ClassLoaderUtil.class.getResourceAsStream(r), fos);
    fos.close();
    

    有这个这个东东,相信大家会减少踩坑,而且大胆地使用java和脚本之间的交互吧。 java可以调用shell,那么shell再调用其他就方便了。 记得一点, 不要过度地依赖缓冲区进行线程之间的通信。原因自己去学习吧。

    希望这个能帮到大家。

    版权声明:本文内容由互联网用户自发贡献,版权归作者所有,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:yqgroup@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

    用云栖社区APP,舒服~

    【云栖快讯】云栖社区技术交流群汇总,阿里巴巴技术专家及云栖社区专家等你加入互动,老铁,了解一下?  详情请点击

    展开全文
  • -- 启用 cmdshell 权限 EXEC sp_configure 'show advanced options', 1 GO -- 重新配置 RECONFIGURE GO -- 启用xp_cmdshell EXEC sp_configure 'xp_cmdshell', 1 GO --重新配置 RECONFIGURE GO -- ...
  • process这个类是一个抽象类,封装了一个进程(你在调用linux的命令或者shell脚本就是为了执行一个在linux下执行的程序,所以应该使用process类)。  process类提供了执行从进程输入,执行输出到进程,等待进程完成...
  • Java调用shell脚本要注意工作目录

    千次阅读 2013-01-29 14:04:53
    最近在一个web项目中要调用shell脚本, 把当天生产的一个文件推送到另一台机器上去, 脚本内容大致如下: #!/bin/bash for i in `cat aa` do date=`date +%Y_%m_%d` file=${date}_some.gz /bin/cp $file some....
  • 如何在Android中启动JAVA程序

    万次阅读 2012-07-17 08:05:56
    本人博客原文:... 在Android中启动JAVA程序其实有很多种方式,现总结如下 一、在Android应用程序中发送Intent启动Android应用程序 这个方式最简单,最常用。...关于Intent的更多内容请阅读《Intent技术简介
  • 本文由博主原创,转载请注明出处(保留此处和...此脚本的执行背景是,在一个目录下有多个android工程,我需要在当前目录下执行脚本exec.sh,然后能在所以子目录下,分别编译android工程。   脚本一(exec.sh): #!/b
  • 一开始在网上搜索了一轮,有些人说mac 没有cmd,那么java就不能代码调用mac的终端,后来我稍微试了一些,貌似也好像有这么一回事。 用最简单的,cd +路径,再ls输出。发现ls输出的文件列表根本就是根目录,就是说...
  • 有时候经常会碰到需要远程调用Linux或者本地调用Linux或者本地调用cmd的一些命令,最近小结了一下这几种用法本地调用cmd命令 @Test public void testCmd()throws Exception{ String cmd="cmd /c date"; //命令的...
  • spark-shell是spark提供一个控制台,通过它我们可以方便的学习spark的API,类似于scala的REPL. spark-shell在/bin目录下,下面简单分析一下spark-shell的启动。 spark-shell--------->spark-submit----------
  • 原文 ... 主题ShellJava 背景 我们在开发过程中,大部分是java开发, 而在文本处理过程中,主要就是脚本进行开发。 java开发的特点就是我们可以很早地进行TDDL, METAQ 等等地对接; 而脚本...
  • [Scala Shell脚本执行]

    万次阅读 2018-06-01 12:52:04
    Scala语言来自于Scalable(可伸缩的),...本文主要介绍咋Linux系统中Scala的Shell脚本,Scala源文件,Scala的Jar执行方法。一、Shell脚本运行Scala 创建ScalaTest.sh文件,内容如下:#!/bin/sh exec scala "...
  • 在Jenkins中配置执行远程shell命令

    万次阅读 多人点赞 2014-10-30 18:39:50
    用过Jenkins的都知道,在Build配置那里有一...2. Execute shell 第1个是执行windows命令,第2个是执行shell脚本。 一开始我以为不管jenkins安装在windows下还是linux下都可以执行windows命令和linux命令,但是后
  • java -cp

    万次阅读 2012-07-06 16:02:11
    java -cp classpath ...Specify a list of directories, JAR archives, and ZIP archives to search for class files. Class path entries are separated by colons (:). Specifying -classpath or -cp overrid
  • 背景 我们在开发过程中,大部分是java开发, 而在文本处理... 前阵子我遇到这么一个需求场景: 对抓取的数据进行打包, 后来又遇到我要通过脚本进行抓取,比如nodejs下基于phantomjs的casperjs爬虫。 解决方法
  • mysql触发器调用外部脚本

    千次阅读 2014-09-30 11:55:38
    源码: #在tbls表上面创建触发器 #由于不能查询到刚插入的那条记录。所以只能在这边手动的传参 drop TRIGGER trigger_tbls; create TRIGGER trigger_tbls AFTER INSERT ON hive_metastore.TBLS  ...
  • R语言shell、system、shell.exec函数详解

    千次阅读 2018-07-16 11:15:38
    一、system函数:调用参数command指定的操作系统命令system(command,intern=false,ignore.stdout=false,ignore.stderr=false,wait=true,input=NULL,show.output.on.console=true,minimized=false,invisible=true) ...
1 2 3 4 5 ... 20
收藏数 5,626
精华内容 2,250
关键字:

php 通过shell_exec调用jar