【问题标题】:Running commands in shell scripting在 shell 脚本中运行命令
【发布时间】:2016-04-18 17:00:29
【问题描述】:

我有一个非常简单的 shell 脚本,用于编译和运行 .java 文件。

#!/bin/sh
x-terminal-emulator
javac SomeJavaFile.java
java SomeJavaFile

然而,这个脚本在触发Java 命令之前似乎停止了。本质上,脚本也可能看起来像这样

#!/bin/sh
x-terminal-emulator

我该如何解决这个问题?

编辑

根据建议和答案,我的脚本现在看起来像这样

#!/bin/sh
x-terminal-emulator -e "javac DropboxStatusLoop.java && java DropboxStatusLoop"

但是它会立即打开然后关闭。我认为这很奇怪,因为我的代码中有一个循环。

非常简单,我的代码如下所示

import java.lang.*;

public class SomeJavaFile {
    public static void main(String[] args) {
        for(long i = 0; ; i++) {
            try {
                System.out.println("Hi");
                Thread.sleep(1000);
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
}

手动完成后确实可以正常编译和运行,但是,它与之前提到的终端打开和关闭有相同的问题。我相信这是因为Thread.sleep(1000); 这可能会让终端认为它已经完成了它正在做的事情,所以它会停止并关闭。任何解决此问题的帮助表示赞赏。

【问题讨论】:

  • 为什么需要x-terminal-emulator
  • @cricket_007 我被告知在打开默认终端时使用它
  • 谁告诉的?如果您只是在 chmod +x ./your-script.sh 之后运行 ./your-script.sh,那么您的 java 代码将在当前终端中运行。没有理由创建一个新的。
  • @cricket_007 我看到了混乱。我所做的是设置它,以便在双击时运行脚本文件,所以我想做的是启动一个终端,然后编译并运行 java 程序。当前没有终端
  • 我认为你需要DropboxStatusLoop.java && java DropboxStatusLoop。您的方式会将编译任务置于后台并立即尝试运行代码而无需完成编译。

标签: java linux shell


【解决方案1】:

脚本修复

本节重点介绍脚本本身的问题,并没有涉及同样是问题的 Linux 错误。如果您稍后阅读此答案并且您只是在执行脚本时遇到问题,请参阅以下部分“Linux 的错误修复,Nautilus 用户” 或参阅this post

  • 问题是您的脚本将运行x-terminal-emulator,它会打开一个新的终端实例,然后它会等待该进程完成后再继续。没有任何东西可以让它完成,它只会打开并等待。

Java 编译和运行命令不会传递给x-terminal-emulator,它们只是您的脚本中在x-terminal-emulator 完成运行后执行的命令。

  • 另外,由于您不想运行 java 程序,除非它成功编译,您应该像这样将命令链接在一起:command1 && command2。这样,command2 只会在command1 成功时运行。

要传递Java 命令以在x-terminal-emulator 中运行,请使用-e 选项,如下所示:

x-terminal-emulator -e "javac SomeJavaFile.java && java SomeJavaFile"

这会将命令发送到x-terminal-emulator

  • 除非您特别想在该程序运行时打开另一个 shell,否则您很可能不想使用x-terminal-emulator

只需从脚本中删除该行,整个脚本就变为:

#!/bin/sh
javac SomeJavaFile.java
java SomeJavaFile
  • 您必须确保已按照步骤使您的 shell 脚本可执行,否则必须使用 bashsh 命令从终端运行。

使脚本可执行

要能够通过双击其图标或键入./script.sh 来运行脚本,您需要:

chmod +x script.sh

script.sh 是您的脚本文件的名称。

chmod +x myScript.sh

并在脚本文件的顶部包含“she-bang”行:

#!/bin/bash

然后你可以双击它的图标,或者用./myScript.sh运行它。


针对 Linux、Nautilus 用户的错误修复

在找到作者脚本的问题后,由于 Kali Linux 的一个“错误”,该解决方案仍然无效,与所有 Linux 发行版中的 Nautilus 错误有关。

要修复该错误,必须遵循“使脚本可执行”部分中的所有步骤,以及下一个步骤。

有什么问题?

Kali Linux 的默认行为是在后台运行可执行的 shell 脚本,如果它们被点击(从桌面或文件资源管理器运行)。

大多数 Linux 发行版中的默认文件资源管理器 Nautilus 的默认行为是打开可执行的 shell 脚本以在打开时进行编辑。

这解释了为什么作者的脚本在使用./script.shbash ./script.sh 从终端运行时运行良好。

修复

按照“使脚本可执行”部分中的步骤进行操作后,您需要更改 Nautilus 中的设置。这个解决方案是在here 找到的,在那里进行了更深入的讨论。

这里是解决方案的要点:

  • 通过打开任何文件夹或输入 nautilus 打开文件资源管理器 Nautilus。然后进入这个菜单:

     Edit → Preferences
    
  • 然后转到Behavior 标签,在Executable Text Files 下选择Ask each time。对于非 Kali 用户,我认为您可以选择 Run executable text... 作为默认选项。

Kali 必须配置为Ask each time打开一个可执行的 shell 脚本,选择“运行可执行文本文件...”不起作用! strong> 但是,我确实认为对于其他发行版,您可以选择“运行可执行文本文件....”作为默认行为。


【讨论】:

  • 感谢您的回答,但这会导致更多问题。您能否根据编辑提供进一步的帮助?
  • @Dan,当您尝试制作没有 x-terminal-emulator 部分的 shell 脚本时,您是否确保文件可执行?
  • @Dan 阅读我答案的最后一部分(新编辑),如果有任何改变,请告诉我。
  • @Dan 谢谢 Dan :) 我努力为我的答案付出了很多努力,所以很高兴看到他们的帮助和感谢!
【解决方案2】:

在脚本内部,您正在通过在前台运行的脚本运行程序“x-terminal-emulator”。 因此,它不会将控制权返回给主脚本。 如果您只想通过脚本运行 java 程序,请从脚本中删除该程序。

#!/bin/sh
javac SomeJavaFile.java
java SomeJavaFile

【讨论】: