2016-07-25 6 views
-1

私はLinux(ウィンドウから来ている)に非常に慣れていて、うまくいけば複数のシステムで実行できるスクリプトを書こうとしています。私はこれのためにPythonを使用しようとしましたが、それも難しいです。ここに私がこれまで持っていたものがあります:私がbashに切り替えるとシェルスクリプトがハングアップする - Linux

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... 

スクリプトは2行目(bash)でハングします。私はそれをどうやって解決するか、あるいは私が間違っているかどうかはわかりません。ご意見をお聞かせください。

また、同じネットワーク上の複数のシステムでこのスクリプトを実行する方法のヒントはありますか?

ありがとうございます。

#!/bin/bash 

source /bin/compilervars.sh intel64 

file="$HOME/a.out" 

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

あなたはファイルでこれを入れてchmod +x myscriptとそれが実行可能になるだろう:私はあなたがしたいと思います信じて何

+0

このスクリプトをどのように実行していますか?それは何を目的としていますか?最初にbashとして実行するのではなく、途中でbashを起動しようとしているのはなぜですか? –

+0

あなたがbashスクリプトの作成方法と実行方法の基礎を持っているかどうかわからない。見てください:http://stackoverflow.com/documentation/bash/300/hello-world#t=201607251613433976444 – Sundeep

+1

http://shellcheck.net/にアクセスしてから、人間にデバッグを依頼してください。 – tripleee

答えて

2

。その後、./myscriptで実行します。あるいは、bash myscriptで実行することもできます。

スクリプトはほとんど意味がありません。 2行目は新しいbashセッションを開きますが、セッションを終了するまでそこに座ります。また、ディレクトリを前後に変更することはほとんど必要ありません。別のディレクトリにある単一のコマンドを実行するには、1が通常

(cd /other/place && mycommand) 

(...)を行いますが、サブシェルでこれを実行したいシェルに指示します。 cdはそのサブシェル内で発生し、実行後にはcdに戻る必要はありません。 cdが失敗した場合、コマンドは実行されません。例えば

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

...あるいは変数fileからディレクトリ名を選ぶと、それを使用:

あなたがコードをコンパイルするときは、必ず $HOMEにいるようにしたいかもしれません
if [ -f "$file" ]; then 
    (cd $(dirname "$file") && icc code.c) 
fi 

=の周囲にスペースを入れずに変数を割り当てる必要があります。

同様に、は、私は上記のことを書いたとしてifと内部[ ... ]後のスペースであることをが必要です。

また、スクリプトでは~ではなく$HOMEを使用する傾向があります。

+0

これは機能します!とてもKusalanandaありがとうございました。私はスペースが重要であることを知らなかった(そしてラインもそうであるかもしれない)。知っておいてよかった。私はそれ以上のことを考えています。 – Samy

+0

@Samy Linesは、特にあなたがそれらに物事を入力すると問題になります。 ;-)申し訳ありません、それは冗談でした。空行は関係ありません。スペースは場所に関係します。コマンドにはスペースが必要です。 '[' '実際にはシェルに組み込まれているコマンドです(' man [')参照)、'/bin/['、' if/bin/[-f "$ file "; '' test -f "$ file"と同じです;そうではありません。それから。どうすればあなたをさらに混乱させることができますか? ;-) – Kusalananda

1

シェルスクリプトは、端末に入力されたキーストロークのレコードではありません。あなたはこのようなスクリプトを記述する場合:

command1 
bash 
command2 

それはスクリプトがbashのに切り替え、その後、別のシェルでcommand2を実行することを意味するものではありません。つまり、bashが実行されます。制御端末がある場合、そのbashはプロンプトを表示し、コマンドの入力を待ちます。そのbashを終了するには、exitと入力する必要があります。その後、元のスクリプトはcommand2に進みます。

スクリプトを途中で別のシェルに切り替える方法はありません。これをシミュレートする方法があります。スクリプトは、別のシェルを使用して自身を再実行することができます。これを実行するには、スクリプトに再実行されていることを検出するロジックが含まれている必要があります。これにより、再度実行し直すことを防ぎ、2回実行しないコードをスキップできます。

​​では、このような再実行ハックを実装しました。これは、これらの行で構成されています:

# 
# 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 ${@+"[email protected]"} 
fi 

txr_shell変数(ない変数の標準的な、私の発明)は、このロジックは、それが再実行されていたことを検出する方法です。変数が存在しない場合、これは元の実行です。 export txr_shellを再実行すると、再実行されたインスタンスはこの環境変数を持ちます。

また、変数はシェルへのパスも保持します。これはスクリプトの後半で使用されます。変数SHELLとしてMakefileに渡されるため、ビルドレシピは同じシェルを使用します。上記のロジックでは、txr_shellの内容は関係ありません。これはブール値として使用されます。存在するかどうかです。

上記のコードスニペットのプログラミングスタイルは、非常に古いシェルで動作するように意図的にコード化されています。そのため、最新の構文[ -z "$txr_shell" ]の代わりにtest x$txr_shell = xが使用され、理由は"[email protected]"ではなく、${@+"[email protected]"}が使用されます。

スクリプトの残りの部分は、再実行トリックのおかげで、合理的で現代的なシェルで実行されるため、スクリプトのこの時点以降は使用されなくなりました。

関連する問題