スクリプトを実行するための./とshの違いは何ですか?


71

簡単なスクリプトを書きました。を実行するsh <myscriptname.sh>と正しい出力が得られましたが、実行./<myscriptname.sh>するとエラーが発生しました。

私が行うときの違いは何であるshとは./


15
「エラーが発生しました」と言う代わりに、エラーの内容を貼り付けると役立ちます。
SpashHit

回答:


67

ファイル名をスクリプトインタープリタープログラムに渡してスクリプトを実行すると、スクリプトを引数として渡してインタープリタープログラムを実行します。たとえば、これは引数 'filename.sh'を持つプロセス 'sh'のように見えます。shインタプリタは、ファイルを開いています。

一方、スクリプト自体を実行すると、システムは指定されたインタープリタープログラムを呼び出し、スクリプトの内容をフィードします。この場合、プロセスは引数なしの「filename.sh」のように見えます。

バンラインがあることを確認する必要があります。

#!/bin/bash
# bash script here

bang行は、スクリプトの最初の行であり、同じ2文字#!で始まります。これらは、システムがスクリプトを実行しようとしたときに読み取られ、システムはその直後にプログラムにプログラムを渡します。この行はbashとは関係がなく、Pythonとperlでもまったく同じように機能しますが、それらは非常に異なる言語です。#!/usr/bin/pythonたとえば、使用してから、Pythonコードを使用します。

スクリプトを作成したら、実行権限を設定していることを確認してください。

chmod a+x filename.sh

その後、スクリプトを独自のプロセスとして実行できます。

./filename.sh

または/usr/sbin、どこからでも実行できるように、素敵なプログラム名を持つ既知の場所にファイルを配置します。

sudo cp filename.sh /usr/sbin/program-name
program-name

そして、これは本当に適切なパーミッションでbangラインを使用することの実際的な利点です-それはすべてデプロイについてです。スクリプトを実行するプログラムを覚えておく必要がある場合、ユーザーにスクリプトを実行させるのは非常に困難です。スクリプトを実行するたびに、スクリプトへの完全なパスを忘れずに指定してください。どこにそれを置くよう/usr/local/bin例えば、および実行可能なそれを作る、あなたのスクリプトを使用しようとしている人々のために悲しみの非常に多くを保存することができます。これらのプログラムは、コンピューター上のすべてのユーザーが利用できるようになります。

識別にも適しています。topプログラムにアクセスすると、bang行なしで実行されたスクリプトには、インタープリターの名前(bashperlまたは)が付けられpythonます。ただし、適切な権限でスクリプトを実行すると、スクリプトの名前が表示されます。

注:誰でもアクセスできるスクリプトを配布する場合は、manページとdebパッケージを作成してインストールしてください。オンラインでのランダムスクリプトの数を減らし、アンインストールできるデバッグの数を増やす必要があります。


1
個人用のbinフォルダーを使用することもできます。ホームフォルダーへのbinフォルダーを作成してログアウトし、再度ログインすると、shまたは./なしでそのフォルダー内のスクリプトを実行できるようになります。
パプカイジャ

もちろん、ホームフォルダーをPATHに追加することは少し頭痛の種になることがあります。より良いものをインストールします。パッケージのローカルユーザーインストールを許可するために、デフォルトで〜/ .local / binをパスに追加するという話がありましたが。
マーティンオーウェンズ-doctormo-

デフォルトのインタプリタはbashであることに注意してくださいsh
ネイサンオスマン

1
スクリプトに拡張子を付けないでくださいPATH。特にに配置するときはそうではありません。
ガイラ

1
/usr/local/binおそらくそれよりも良いでしょう/usr/sbin-それは、プログラムがディストリビューションの一部ではなく、このマシンに対してローカルであることを示しています。
グレンジャックマン

41

ショートバージョン:

  • shコマンドラインインタープリター(ダッシュ)です。
    実行sh my_scriptすると、ダッシュがスクリプトを解釈します。

  • ./最初の行を見て、使用するインタープリターを見つけようとします。例えば#!/bin/bash、さらには#!/bin/ruby(実行とは対照的にruby my_script)。


7
実際./に何かを見つけるのではなく、ファイルの最初の2バイトを調べるのはシステム実行メソッドです。
マーティンオーウェンズ-doctormo-

9
絶対に。ここにすべての非常に長い説明があります。私は実用的です:)
ステファノパラッツォ

使用shしてファイルにsha-bangが含まれている場合、sha-bangは無視されるのshでしょうか、それともリンクのあるシェルを開いてから、他のシェルを開くのでしょうか?
イニ

5

あなたがする違いは、

  • を使用するとsh、端末の対話型プロンプトで入力したのと同じようにスクリプト内の行を解釈するプログラムを実行しています。

  • ./スクリプトがあなたが座っているAND(例えば、あなたが発行したので、それが実行可能になり、現在のディレクトリにちょうどここにあると仮定してショートカットを作っているchmod +x myscript.sh:-)将来の時間のためにあなたの貴重な時間を節約し、)


3
+1は、ファイルが実行可能でなければならないことを簡潔に述べる唯一のものであるためです。
ミケル

2
shファイルは必ずしも実行可能である必要はないことに注意してください。
イニ

3

エラーが発生する主な理由は3つあります。

  • ファイルはそれを修正するために実行
    chmod +x <myscriptname.sh>れません
  • パーティションでスクリプトの実行が許可されていない(マウントされている " noexec")
    スクリプトを/usr/local/bin
  • #!行にエラーがあり
    、最初の行があることを確認します#!/bin/sh#!/bin/bash

最初の行が正しいように見えても動作しない場合は、ファイルにDOS行末記号がないことを確認してください。

エラーは次のようになります。

$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory

を実行することで修正できますdos2unix <myscriptname.sh>。または、お持ちでない場合は、をご覧ください
perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>


0

答えは、shは非常に人気のあるシェルの名前だということです。しかし、時代遅れで、他のものに置き換えられました。現在、shはマシンにインストールされている他のシェルにリンクされています。例えば、私はそこにパッシュを入れました。shからシェルを実行すると、通常、元の「シェル」動作との「互換性」モードがトリガーされます。

したがって、解決策は非常に簡単です。shコマンドの背後にあるもの(ls -al / bin / sh)を見て、#!/ bin / whatever_you_find_thereを最初の行に追加します(またはスクリプトにそのようなものがある場合は編集します)。

または、スクリプト自体にバグがある可能性があります。shが満たす依存関係と同様ですが、実際に使用されるインタープリターはそうではありません。


0
mkdir ~/bin ; cp myscript.sh ~/bin/

echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ; 

ではなく/usr/sbin、それは非必須の管理ツールのためで/usr/local/binあり、を持ちたくない場合はより良い選択ですが、可能な限り~/bin/避けるsudoことをお勧めします。


Ubuntuでは、デフォルトには~/.profileすでにが~/bin存在する場合、を追加するためのコードがありますPATH。別の注意として、スクリプトに拡張子を付けないでください。
ガイラ

1
<myscriptname.sh>を参照していましたが、スクリプトに拡張子を付けない理由は何ですか?そのように表示されるプレーンテキストファイルがあることで、〜/ bin /に保持しているバイナリを編集しようとすることを防いでいるので、私は通常そうします。(ls ~/bin/|wc -l = 428)私はそこにたくさんのものを入れました;)
Joey1978

特定のタスクを達成するためのスクリプトを書くと想像してください。次に、この特定のスクリプトをpythonで記述すると、はるかに効率的になるので、pythonで書き直します。2つの選択肢があります。1)非常に紛らわしい.sh-extensionのままにするか、2)スクリプトの名前を変更し、スクリプトのすべての使用を検索して置き換え、新しい名前を使用します。あなたがスクリプトを見れば/bin/usr/bin、あなたは、彼らが拡張機能を使用しないでください表示されます。
ガイラ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.