2

000 パーミッションで Bash 関数を実行できるのは完全に正しいわけではありませんが、ほぼ正しいです。私のコードは次のとおりです。

#!/bin/bash
function hello {
echo Hello! }

hello ファイルには次の権限があります。

-r--------  1 UnixBasics hello_file

まず、現在の権限で次のように入力します。

$ . ./hello_file;hello

微調整は、bash スクリプト スクリプトを実行する直前に 400 パーミッションを 000 に変更することです。

$ chmod 000 hello_file
$ . ./hello_file;hello                                             [1]
-bash: ./hello_file: Permission denied 
Hello!

1 つのエラーが発生しますが、関数の実行は停止しません。私は理解できない。hello-function の設定を解除しました: 「unset hello」。エラーが表示されます:

-bash: ./hello_file: Permission denied
-bash: hello: command not found

なぜ最初にそれらを取得できなかったのですか? キャッシュ、バッファなどと関係がありますか? 000 パーミッションで Bash スクリプトを実行できるのはなぜですか? [1]

4

4 に答える 4

11

スクリプトを実行しているのではなく、スクリプトをソース(含めて) しています。スクリプトを入手するには、読み取り権限のみが必要です。

ちなみに、関数は単に存在するだけで、権限はありません。ファイルが読み込まれ、関数が定義されたら、必要なだけ実行できます。


アップデート:

なぜ最初にそれらを取得できなかったのですか? キャッシュ、バッファなどと関係がありますか?

はい、Pax が答えたように、hello はおそらく以前にファイルのソースから定義されていました。ソーシング ("." 組み込みコマンド) が何をするのか混乱するかもしれません。Sourcing はファイルを読み取り、そのすべてのコマンドを現在のシェルで実行してから、プロンプトに戻ります。したがって、ファイルを一度実行すると、その関数は現在のシェル インスタンスで定義され、そのシェル セッションを終了する (または設定を解除する) までそこにとどまります。

000 パーミッションで Bash スクリプトを実行できるのはなぜですか? [1]

できません。エラーが表示されることに注意してください。あなたの出力を引用する:

$ . ./hello_file;hello                                             [1]
-bash: ./hello_file: Permission denied 
Hello!

1 つのコマンドラインで 2 つのコマンドを実行しました。「アクセス許可が拒否されました」でソーシングが失敗しました。「こんにちは!」出力は、ファイルの以前のソースからのものです。設定を解除して同じコマンドラインを再試行したときに、自分で証明しただけです。

それをキャッシングと呼ぶことはできません...それがシェルの仕組みです。別のファイルをソースすると、そのすべての定義が現在のシェル セッションに含まれ、そこにとどまります。実際にスクリプトを実行すると (ソーシングではなく)、現在のセッションで残留物が発生することはありません。

$ chmod +x hello_file
$ ./hello_file           # note: executed, not sourced
$ hello
-bash: hello: command not found
于 2009-03-25T23:59:06.420 に答える
5

最も可能性の高い説明は、hello_file が保護される前に実行され、関数が既に作成されていることです。次に、スクリプトを保護しました (コマンドでは 100 と言いましたが、テキストでは 000 に言及しました)。

そのため、スクリプトは実行されません。しかし、hello() は前回の実行からまだ定義されています。

新しいシェルを開くか、単に実行してみてくださいunset hello

于 2009-03-26T00:02:19.720 に答える
2

モードを 100 に変更する前に、スクリプトを読み込みましたか (つまり、". ./hello_file" を実行しましたか)。その場合、「hello」関数は単純に bash にロードされます。その後、読み取り不能なファイルを入手しようとしても、それは変わりません。正しくテストするには、必ず新しいシェルを起動してください。

于 2009-03-26T00:04:28.730 に答える
2

プログラムを実行するには (bash スクリプトかバイナリ実行可能ファイルかに関係なく)、実行権限が必要です。コマンドを入力すると、最初の単語 (./foo以下の例など) で実行するコマンドが指定され、別のプロセスとして起動されます。シェル スクリプトの場合、#!行にリストされているシェル インタープリターの新しいコピーを実行し、そのインタープリターを使用してプログラムを実行します。

$ ls -l foo
-rw-r--r-- 1 ラムダ ラムダ 23 3 月 25 20:02 foo
$ chmod 744 foo # または chmod u+x foo
$ ls -l foo
-rwxr--r-- 1 ラムダ ラムダ 23 3 月 25 20:02 foo
$ ./フー
こんにちは

コマンドを使用する場合.、それはファイルを現在のシェルにソースするように指示するシェル組み込みコマンドです。つまり、現在のファイル内で、コマンド ラインからコマンドを実行したかのように、ファイル内のコマンドが実行されます。ファイルを入手するには、読み取り権限のみが必要です。たとえば、サブプロセスで変数を設定しても、現在のシェルの値は変更されません。ただし、bash スクリプトを現在のシェルにソースすると、値が変更されます。

$ foo=バー
$ 猫セット変数
#!/ビン/sh

foo=こんにちは
$ ./セット変数
$ エコー $foo
バー
$ . ./セット変数
$ エコー $foo
こんにちは

シェル関数(あなたの例のように)は変数によく似ていますが、現在のシェルではコマンドのように機能します。hello_fileそのため、 usingをソースする.と、現在のシェルでその関数が定義され、定義した他のシェル関数と同様に実行できます。

パーミッションに関する限り、パーミッションを 100 に変更する前に、私はそれを賭けます (これは実行可能のみを意味し、読み取り不可を意味します。これは、ファイルを読み取って実行できる必要があるため、ファイルにはまったく役に立ちません) 、あなたはすでにファイルを現在のシェルに取り込んでいます。これは、関数が既に定義されていることを意味し、定義後のファイルのアクセス許可は問題ではありません。関数が現在のシェルで定義されたら、ファイルを削除することもできます。そのシェルがまだ開いている限り、関数は定義されたままです。

編集:編集した質問からわかるように、関数の設定を解除すると、エラーが発生します。これは、私の仮説が正しかったこと、およびアクセス許可を変更する前に既にファイルを入手していたことを強く示しています。説明したように、ファイルの取得と実行はまったく異なる操作であり、ファイルを取得すると、そのアクセス許可 (または存在) はまったく問題になりません。関数は、現在実行中のシェルに既にロードされています。unset hello;を実行した後に元の実験を実行するとわかります。その場合chmod 000、読み取り権限を持ってはいけません。関数は定義されません。

于 2009-03-26T00:12:43.453 に答える