シェルスクリプトを実行するさまざまな方法


44

スクリプトを実行する方法はいくつかありますが、私が知っている方法は次のとおりです。

/path/to/script # using the path (absolute or relative)
. script        # using the . (dot)
source script   # using the `source` command

これ以上ですか?それらの違いは何ですか?あるものを使用する必要があり、別のものを使用する必要がない状況はありますか?


以下の質問と回答、特にショーンのおかげで、知っておくといいでしょう。いくつかのテストを実行するまで、あまりはっきりしなかった何かを追加したいと思います。上記の2番目の方法で「/」を含めると、コマンドは上記のモード1になります。つまり、「./ myscript.sh」はモード1に従いますが、「。myscript.sh」はモード2に固定されます。「パス(絶対または相対)の使用」について言及しましたが、これを明らかにしたかっただけです。
アルン

回答:


32

別の方法は、インタープリターを呼び出してスクリプトへのパスを渡すことです。

/bin/sh /path/to/script

ドットとソースは同等です。(編集:いいえ、そうではありません。KeithBが別の答えのコメントで指摘しているように、「。」はbashに関連するシェルでのみ機能し、「source」はbashおよびcshに関連するシェルの両方で機能します。) -place(スクリプトをコピーして貼り付けたかのように)。これは、スクリプト内のすべての関数と非ローカル変数が残ることを意味します。また、スクリプトがディレクトリへのcdを実行する場合、終了してもそこにいることを意味します。

スクリプトを実行する他の方法では、独自のサブシェルで実行されます。スクリプトの変数は、完了してもまだ生きていません。スクリプトがディレクトリを変更した場合、呼び出し環境には影響しません。

/ path / to / scriptと/ bin / shスクリプトはわずかに異なります。通常、スクリプトの冒頭には次のような「シバン」があります。

#! /bin/bash

これは、スクリプトインタープリターへのパスです。実行時とは異なるインタープリターを指定すると、動作が異なる場合があります(またはまったく機能しない場合があります)。

たとえば、PerlスクリプトとRubyスクリプトは(それぞれ)で始まります:

#! /bin/perl

そして

#! /bin/ruby

を実行してこれらのスクリプトの1つを実行する/bin/sh scriptと、それらはまったく機能しません。

Ubuntuは実際にはbashシェルを使用しませんが、dashと呼ばれる非常によく似たシェルを使用します。bashを必要/bin/sh scriptとするスクリプトは、dashインタープリターを使用してbashスクリプトを呼び出したばかりなので、実行によって呼び出された場合、わずかに間違って動作する可能性があります。

スクリプトを直接呼び出すことと、スクリプトパスをインタープリターに渡すことのもう1つの小さな違いは、スクリプトを直接実行するために実行可能としてマークする必要がありますが、インタープリターにパスを渡すことによって実行することではありません。

別の小さなバリエーション:スクリプトを実行するこれらの方法のいずれかにevalを付けることができます。

eval sh script
eval script
eval . script

等々。実際には何も変わりませんが、徹底のために含めると思いました。


6
「Ubuntuは実際にはbashシェルを使用しない」と言うのは不正確であり、技術的に間違っています。Ubuntu bashシェルを使用ます。ポイントはにsh対応しdashていbashますが、ではありません。
ファヒムミタ

@Shawn最初に、「スクリプトをインプレースで実行します(スクリプトをコピーして貼り付けたように)。これは、スクリプト内の関数と非ローカル変数が残っていることを意味します」。ここの2行目はどういう意味ですか?説明してください。
オタク

@Geekは、子プロセスとしてスクリプトを実行すると(通常の方法)、それが定義する変数と関数(環境)は、プロセスが終了すると消えます。スクリプトを入手すると、これらの変数と関数は現在の環境で作成されます。スクリプトが終了しても、環境への変更は残ります。
ショーンJ.ゴフ

@ ShawnJ.Goff明確化に感謝します。+1。
オタク

プロットツイスト:Bourne Shell(sh)はドットのみを受け入れます。bash組み込みであるため、ソースは受け入れません。pubs.opengroup.org/onlinepubs/9699919799/utilities/… したがって、最も移植性の高い方法はドットです。
デザ

9

ほとんどの人は、次のデバッグフラグをスクリプトに追加して、シェルスクリプトをデバッグします。

set -x     # Print command traces before executing command.
set -v     # Prints shell input lines as they are read.
set -xv    # Or do both

ただし、これは、エディターでファイルを開き(ファイルを編集する権限がある場合)、のような行を追加しset -xてファイルを保存し、ファイルを実行する必要があることを意味します。その後、同じ手順を実行しset -x、などを削除する必要があります。これは面倒な場合があります。

すべてを行う代わりに、コマンドラインでデバッグフラグを設定できます。

$ bash -x ~/bin/ducks
+ du -cks -x dir1 dir2 dir3 file1 file2 file3
+ sort -n
+ tail .ducks
123 etc
424 bin
796 total



$ sh -xv ~/bin/ducks  
#!/usr/bin/env bash

# Find the disk hog
# Borrowed from http://oreilly.com/pub/h/15
...
...

2
関連するヒント:emulate sh 2>/dev/nullシェルスクリプトの一番上に置く習慣になりました。zshで実行すると、これによりPOSIX互換モードになります。他のシェルで実行した場合、この行は効果がありません。次に、でスクリプトを実行できますzsh -x /path/to/script。ここでzshが好きなのは、bashやkshよりも良いトレースを提供するからです。
ジル 'SO-悪であるのをやめる

7

ショーンJ.ゴフは多くの良い点を挙げましたが、ストーリー全体は含まれていませんでした。

Ubuntuは実際にはbashシェルを使用しませんが、dashと呼ばれる非常によく似たシェルを使用します。/bin/shダッシュインタープリタを使用してbashスクリプトを呼び出しただけなので、bashを必要とするスクリプトは、スクリプトを実行して呼び出されたときにわずかに間違って動作する可能性があります。

多くのシステムスクリプト(init.dや/ etcなど)にはシバン#!/bin/shがあります/bin/shが、実際には別のシェルへのシンボリックリンクです(以前/bin/bashは最近)/bin/dash。しかし、それらの1つがとして呼び出される/bin/shと、動作が異なります。つまり、POSIX互換モードに固執します。

彼らはどうやってこれをしますか?さて、彼らはどのように呼び出されたかを検査します。

シェルスクリプト自体は、それがどのように呼び出されたかをテストし、それに応じて異なることを実行できますか?はい、できます。したがって、それを呼び出す方法は常に異なる結果につながる可能性がありますが、もちろんあなたを困らせることはほとんどありません。:)

経験則として:bashのような特定のシェルを学習していて、bashチュートリアルからコマンドを作成する場合は、特に明記されている場合を除き#!/bin/bash、ではなく見出しを付けてください#!/bin/sh。そうしないと、コマンドが失敗する可能性があります。スクリプトを自分で書かれていない場合や、(それを直接呼び出して./foo.shbar/foo.sh()の代わりに、シェルを推測しsh foo.shsh bar/foo.sh)。シバンは正しいシェルを呼び出す必要があります。

そして、他の2種類の呼び出しがあります。

cat foo.sh | dash
dash < foo.sh

5

.そしてsource、サブプロセスを生成せず、現在のシェルでコマンドを実行するという点で同等です。これは、スクリプトが環境変数を設定するとき、または現在の作業ディレクトリを変更するときに重要です。

パスを使用するかパス/bin/shを指定すると、コマンドが実行される新しいプロセスが作成されます。


2
sh script
bash script

もっとあるかどうか考えています...

.source同じです。実行後、環境の変更はscript保持されます。通常、Bashライブラリのソースとして使用されるため、ライブラリはさまざまなスクリプトで再利用できます。

また、現在のディレクトリを保持する良い方法です。スクリプトでディレクトリを変更すると、そのスクリプトを実行するシェルには適用されません。ただし、実行するためにソースを指定すると、スクリプトの終了後、現在のディレクトリが保持されます。


2
.sh / bashおよび関連するシェルでのみ機能します。 sourcecshおよび関連するシェルでも機能します。
KeithB


1
. ./filename
# ( dot space dot slash filename )

ディレクトリがパスにない場合、現在のシェルでスクリプトを実行します。


1

。とソースは少なくともzshでは少し異なります(私が使用しているものです)

source file

動作中

. file

必要ない

. ./file
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.