存在する.sh

存在する.sh

約20個の小さなファイルで構成されるプロジェクトがあります.sh。通常、どのファイルにも20行以上のコードがないため、「小さい」と命名しました。私はモジュラーアプローチをとりました。Unixの哲学そしてプロジェクトを維持する方が簡単です。

各ファイルの先頭.sh#!/bin/bash

簡単に言えば、スクリプト宣言は2つの目的に使用されることを理解しています。

  1. これは、ユーザーがファイルを実行するために必要なシェルが何であるかを覚えるのに役立ちます(たとえば、数年間ファイルを使用していない後など)。
  2. これにより、スクリプトが特定のシェル(この場合はBash)を介してのみ実行されるため、他のシェルを使用するときの予期しない動作を防ぎます。

プロジェクトが5つのファイルから20のファイルに、または20のファイルから50のファイルに増え始めると(単純なデモ用ではない)、20行または50行になります。ワイヤースクリプト宣言。認めます。何人かの人々にとってこれは興味深いかもしれませんが、私には20または50と言うのが少し重複しているように感じます。アイテムごとに1つ(おそらくマスターファイルプロジェクト)。

一部の基本ファイルで、いくつかの「グローバル」スクリプト宣言を使用して、いわゆる20行または50行以上のスクリプト宣言行の重複を回避する方法はありますか?

答え1

現在のプロジェクトが50個のBashスクリプトで構成されていても、すぐにPerlやPythonなどの他の言語で書かれたスクリプトが蓄積し始めます(これらのスクリプト言語にはBashにはない利点があるため)。

各スクリプトに正しい#!-line がない場合は、次のようになります。とても難しいどのインタプリタを使用すべきかわからず、さまざまなスクリプトで作業します。すべてのスクリプトが実行されるかどうかは問題ではありません。他のスクリプトから、これはエンドユーザーの困難を開発者にのみ伝えます。どちらのグループも、スクリプトを使用するためにスクリプトがどの言語で書かれているかを知る必要はありません。

-line および明示的なインタプリタなしで実行されるシェルスクリプトは、#!呼び出されるシェルによって異なる方法で実行されます (たとえば、質問を参照)。Shebangなしでスクリプトを実行するシェルインタプリタとは何ですか?特にスティーブンの答え)これは本番環境では望ましくありません(一貫した動作と移植性が必要です)。

明示的なインタプリタを使用して実行されたスクリプトは、-lineの内容に関係なく#!そのインタプリタによって実行されます。 Pythonや他の言語でBashスクリプトを再実装することにした場合、追加の問題が発生します。

追加のキーストロークを消費し、常に#!各スクリプトに1行を追加する必要があります。


一部の環境では、すべてのプロジェクトのすべてのスクリプトに定型句法テキストが複数あります。#!プロジェクトで「重複」と感じられるラインにすぎないことに満足してください。

答え2

あなたはポイントを見逃しています#!。それは実際に指示するオペレーティングシステムに移動し、定義されたインタプリタでプログラムを実行します。

したがって、スクリプトを書くことができ、#!/usr/bin/perl結果プログラムを実行することができ、./myprogramPerlインタプリタを使うことができます。同様に、#!/usr/bin/pythonプログラムはPythonで実行されます。

したがって、この行はオペレーティング#!/bin/bashシステムにbashでこのプログラムを実行するように指示します。

例は次のとおりです。

$ echo $0
/bin/ksh

$ cat x
#!/bin/bash

ps -aux | grep $$

$ ./x
sweh      2148  0.0  0.0   9516  1112 pts/5    S+   07:58   0:00 /bin/bash ./x
sweh      2150  0.0  0.0   9048   668 pts/5    S+   07:58   0:00 grep 2148

したがって、私のシェルはkshですが、#!プロセスリストにはっきりと見えるこの行のため、 "x"プログラムはbashで実行されています。

答え3

存在する.sh

悪いことは.shファイル名の末尾にあります。

Pythonでこれらのスクリプトの1つを書き換えると想像してください。

最初の行を変更する必要があります。#!/usr/bin/python3ファイルの他のすべてのコード行も変更する必要があるため、それほど悪くはありません。ただし、ファイル名もprog.sh。あなたが知っている誰かに助けることができます。ただし、バージョン管理ツールには関係のないファイルに対する多くの変更が表示されるようになりました。prog.pysed -e 's/.sh/.py/g'

または、Unixの方法でプログラム名をprognotとして指定してくださいprog.sh

存在する#!

正しいものがある場合は、#!実行を含めるように権限/モードを設定してください。だから通訳を知る必要はありません。コンピュータはあなたのためにそれを行います。

chmod +x prog #on gnu adds execute permission to prog.
./prog #runs the program.

Gnu以外のシステムでは、マニュアルを読んでchmod(そして8進法を学ぶ)、とにかく読むことができます。

答え4

一部の基本ファイルで、いくつかの「グローバル」スクリプト宣言を使用して、いわゆる20行または50行以上のスクリプト宣言行の重複を回避する方法はありますか?

はい。移植性またはPOSIXコンプライアンスと呼ばれます。常に移植可能でシェルに拘束されないようにスクリプトを書くようにしてください。スクリプト#!/bin/shが使用されるか、または対話的に使用されている場所/bin/sh(または少なくともPOSIX互換シェル、たとえばksh)からのみスクリプトをインポートします。

ただし、移植可能なスクリプトは、次のことを防ぐのに役立ちません。

  • シェルの機能の1つを使用する必要があります(イルカチュウの答え例です)
  • シェル(PythonとPerl)よりも高いレベルのスクリプト言語を使用する必要があります。
  • PEBKACエラー:あなたのスクリプトは、代わりにあなたのスクリプトを実行したユーザーJ.Doeの手に渡されました。あなたたとえば、意図的にこれを行い/bin/shますcsh

私の意見を表現すると、削除による「重複を避けること」#!は間違った目標です。目標は言葉のないパフォーマンスと実際に動作するスクリプト特定の一般規則に従って効率的に極端なケースを考えてみましょう。lsを解析しないでくださいまたは単語の区切りが必要ない限り、常に変数を引用します。

これは、ユーザーがファイルを実行するために必要なシェルが何であるかを覚えるのに役立ちます(たとえば、数年間ファイルを使用していない後など)。

これは実際にはユーザーのためではありません。オペレーティングシステムが正しいインタプリタを実行するように設計されています。この場合、「正しい」とは、オペレーティングシステムがshebangにあったことを発見したことを意味します。以下のコードが間違ったシェルの場合、これは作者の間違いです。ユーザーメモリに関しては、Microsoft WordやGoogle Chromeなどのプログラムの「ユーザー」は、そのプログラムが作成者がどの言語で書かれているのかを知る必要はないと思います。

そして、移植可能なスクリプトはPOSIX準拠のシェルで動作する必要があるため、元々使用したシェルを覚えておく必要さえないかもしれません。

これにより、スクリプトが特定のシェル(この場合はBash)を介してのみ実行されるため、他のシェルを使用するときの予期しない動作を防ぎます。

彼らはこれをしません。予期しない動作を実際に防ぐ方法は、移植可能なスクリプトを作成することです。

関連情報