当我切换到bash时Shell脚本挂起 - Linux

时间:2016-07-25 16:12:23

标签: linux bash shell

我非常非常熟悉Linux(来自Windows)并试图编写一个我希望可以在多个系统上执行的脚本。我尝试使用Python,但也很难。以下是我到目前为止的情况:

cd /bin
bash
source compilervars.sh intel64
cd ~
exit #exit bash
file= "~/a.out"
if[! -f "$file"]
then
icc code.c
fi

#run some commands here...

脚本挂在第二行(bash)。我不确定如何解决这个问题,或者我是否做错了。请指教。

此外,有关如何在同一网络上的多个系统上运行此脚本的任何提示?

非常感谢。

2 个答案:

答案 0 :(得分:2)

我相信你想做的事情:

#!/bin/bash

source /bin/compilervars.sh intel64

file="$HOME/a.out"

if [ ! -f "$file" ]; then
    icc code.c
fi

您可以将其放在一个文件中,并使其chmod +x myscript可执行。然后,您将使用./myscript运行它。或者,您可以使用bash myscript运行它。

你的脚本没什么意义。第二行将打开一个新的bash会话,但它会一直坐在那里直到退出它。此外,很少需要来回更改目录。要在另一个目录中执行单个命令,通常会执行

( cd /other/place && mycommand )

( ... )告诉shell你想在子shell中执行此操作。 cd发生在该子shell中,并且在完成后不需要cd。如果cd失败,则不会运行该命令。

例如:您可能希望在编译代码时确保您在$HOME中:

if [ ! -f "$file" ]; then
  ( cd $HOME && icc code.c )
fi

...甚至从变量file中挑出目录名并使用:

if [ -f "$file" ]; then
  ( cd $(dirname "$file") && icc code.c )
fi

分配给变量需要在我编写时发生,=周围没有空格。

同样,需要if之后和[ ... ]之内的空格,就像我在上面写的那样。

我还倾向于在脚本中使用$HOME而不是~,因为它更具描述性。

答案 1 :(得分:1)

shell脚本不是键入终端的击键记录。如果您编写如下脚本:

command1
bash
command2

这并不意味着脚本将切换到bash,然后在不同的shell中执行command2。这意味着将运行bash。如果有一个控制终端,那个bash会显示一个提示并等待输入一个命令。你必须输入exit才能退出该bash。只有这样,原始脚本才会继续command2

无法将脚本中途切换到其他shell。有办法模拟这个。脚本可以使用不同的shell重新执行自身。为了做到这一点,脚本必须包含逻辑来检测它是否被重新执行,以便它可以防止再次重新执行自己,并跳过一些不应该运行两次的代码。

this script中,我实施了这样的重新执行黑客攻击。它由以下几行组成:

#
# The #!/bin/sh might be some legacy piece of crap,
# not even up to 1990 POSIX.2 spec. So the first step
# is to look for a better shell in some known places
# and re-execute ourselves with that interpreter.
#

if test x$txr_shell = x ; then
  for shell in /bin/bash /usr/bin/bash /usr/xpg4/bin/sh ; do
    if test -x $shell ; then
       txr_shell=$shell
       break
    fi
  done
  if test x$txr_shell = x ; then
    echo "No known POSIX shell found: falling back on /bin/sh, which may not work"
    txr_shell=/bin/sh
  fi
  export txr_shell
  exec $txr_shell $0 ${@+"$@"}
fi

txr_shell变量(不是标准变量,我的发明)是这个逻辑检测到它被重新执行的方式。如果变量不存在则这是原始执行。当我们重新执行export txr_shell时,重新执行的实例将具有此环境变量。

该变量还包含shell的路径;稍后在脚本中使用;它作为Makefile变量传递给SHELL,因此make build配方使用相同的shell。在上面的逻辑中,txr_shell的内容无关紧要;它被用作布尔值:它是存在还是不存在。

上面代码片段中的编程风格是故意编码的,适用于非常旧的shell。这就是使用test x$txr_shell = x代替现代语法[ -z "$txr_shell" ]的原因,以及为什么使用${@+"$@"}而不仅仅是"$@"

此脚本之后不再使用此样式,因为 由于重新执行技巧,脚本的其余部分运行在一些优秀的,相当现代的shell中。