序文最近、bash スクリプトの構文を学んでいますが、bash 構文に慣れていないと、未定義の変数を表示するなど、間違いを犯しやすくなります。シェルで変数が定義されていない場合でも、その変数は使用できますが、結果は期待どおりにならない可能性があります。例えば: #!バイナリ # ここでは、変数 var が文字列 abc と等しいかどうかを判断していますが、変数 var は宣言されていません if [ "$var" = "abc" ] それから # if 判定が真の場合、コンソールに「not abc」と出力します echo "abcではない" それ以外 # if 判定が偽の場合、コンソールに「abc」と出力します 「abc」をエコーする フィ 結果として、abc が印刷されますが、問題は、このスクリプトがエラーを報告する必要があることです。変数に値が割り当てられていないことがエラーです。 これらのエラーを修正するには、スクリプトの先頭に次の行を追加することを学びました: このコマンドは、スクリプトがそれを先頭に追加し、存在しない変数に遭遇した場合はエラーを報告して実行を停止することを意味します。 再度実行すると、次のメッセージが表示されます: もう一度、最初に削除しようとしていたと想像してください: rm -rf $dir/* すると dir が空になります。何が起こるでしょうか? rm -rf は削除コマンドです。$dir が空の場合は、rm -rf /* を実行するのと同じになり、すべてのファイルとフォルダーが削除されます。 。 。すると、システムが消えてしまいます。これは、データベースを削除して逃げるという伝説的な行為なのでしょうか? ノードやブラウザ環境であれば、var === 'abc' を直接使用すると確実にエラーが発生します。つまり、多くの JavaScript プログラミング経験は bash では再利用できません。再利用できれば最高です。 その後、私は探索を始めました。bash の代わりに node スクリプトを使用できれば素晴らしいだろうと思いました。1 日中試行錯誤した後、私は徐々に魔法のツール、Google の zx ライブラリを発見しました。心配しないでください。このライブラリはまだ紹介しません。まず、主流が node を使用して bash スクリプトを記述する方法を見てみましょう。そうすれば、なぜそれが魔法のツールであるかがわかります。 ノードで bash スクリプトを実行する: 不本意な解決策: child_process API たとえば、child_process APIのexecコマンド const { exec } = require("child_process"); exec("ls -la", (エラー, stdout, stderr) => { if (エラー) { console.log(`エラー: ${error.message}`); 戻る; } (標準エラー出力)の場合{ console.log(`stderr: ${stderr}`); 戻る; } console.log(`stdout: ${stdout}`); }); ここで注目すべき点は、まず、exec は非同期ですが、bash スクリプト コマンドの多くは同期であるということです。 また、注意: エラー オブジェクトは stderr とは異なります。child_process モジュールがコマンドを実行できない場合、エラー オブジェクトは空ではありません。たとえば、ファイルが見つからない場合、エラー オブジェクトは null ではありません。ただし、コマンドが正常に実行され、標準エラー ストリームにメッセージが書き込まれる場合、その stderr オブジェクトは null にはなりません。 もちろん同期execコマンドexecSyncを使用することもできます。 // child_process モジュールから exec コマンドをインポートします。const { execSync } = require("child_process"); // hello という名前のフォルダーを同期的に作成します。execSync("mkdir hello"); bash コマンドを実行できる child_process の他の API を簡単に紹介しましょう。
exec と ececFile の違いは、exec はコマンドの実行に適しているのに対し、eexecFile はファイルの実行に適していることです。 Node が bash スクリプトを実行する: 高度なソリューション shelljs シェルは 'shelljs' を必要とします。 # ファイルを削除するコマンド shell.rm('-rf', 'out/Release'); // ファイルのコピーコマンド shell.cp('-R', 'stuff/', 'out/Release'); # lib ディレクトリに切り替え、ディレクトリ内の .js で終わるファイルを一覧表示し、ファイルの内容を置き換えます (sed -i はテキストを置き換えるコマンドです) shell.cd('lib'); shell.ls('*.js').forEach(関数 (ファイル) { shell.sed('-i', 'BUILD_VERSION', 'v0.1.2', ファイル); shell.sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', ファイル); shell.sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, shell.cat('macro.js'), ファイル); }); シェル.cd('..'); # 特に指定がない限り、指定されたコマンドを同期的に実行します。 同期モードでは、ShellStringを返します。 # (ShellJS v0.6.x と互換性があり、{ code:..., stdout:..., stderr:... } という形式のオブジェクトを返します)。 # それ以外の場合は、サブプロセス オブジェクトが返され、コールバックは引数 (コード、stdout、stderr) を受け取ります。 if (shell.exec('git commit -am "自動コミット"').code !== 0) { shell.echo('エラー: Gitコミットに失敗しました'); シェルを終了します(1); } 上記のコードから判断すると、shelljs は nodejs で bash スクリプトを書くための非常に優れたソリューションです。node 環境を自由にアップグレードできない場合は、shelljs で十分だと思います。 続いては17.4kからスタートした本日の主人公、zxを見てみましょう。 zxライブラリ公式サイト: www.npmjs.com/package/zx まずは使い方を見てみましょう #!/usr/bin/envzx です $`cat package.json | grep name` を待ちます ブランチ = $`git ブランチ --show-current` を待機します $`dep deploy --branch=${branch}` を待機します Promise.all([ を待つ $`スリープ1; エコー1`、 $`スリープ2; エコー2`、 $`スリープ3; エコー3`、 ]) 名前を 'foo bar' にします $`mkdir /tmp/${name} を待つ どう思いますか? Linux コマンドを記述するだけです。多くの bash 構文を無視して、js を直接使用できます。その利点はそれだけではありません。その機能のいくつかは非常に興味深いものです: 1. ts をサポートし、.ts を .mjs ファイルに自動的にコンパイルします。.mjs ファイルは、上位バージョンの Node.js で es6 モジュールをサポートするファイル拡張子です。つまり、このファイルは他のツールでエスケープすることなくモジュールを直接インポートできます。 2. パイプライン操作パイプ方式をサポート 3. ネットワーク リクエスト用の fetch ライブラリ、カラー フォントを印刷するための chalk ライブラリ、エラー処理用の nothrow メソッドが付属しています。bash コマンドが失敗した場合は、このメソッドでラップしてエラーを無視できます。 完全な中国語文書(私の翻訳スキルの低さをお許しください) #!/usr/bin/envzx です $`cat package.json | grep name` を待ちます ブランチ = $`git ブランチ --show-current` を待機します $`dep deploy --branch=${branch}` を待機します Promise.all([ を待つ $`スリープ1; エコー1`、 $`スリープ2; エコー2`、 $`スリープ3; エコー3`、 ]) 名前を 'foo bar' にします $`mkdir /tmp/${name} を待つ Bash は素晴らしいですが、スクリプトを書くときは、通常、より便利なプログラミング言語が選択されます。 JavaScript は最適な選択ですが、標準の Node.js ライブラリを使用するには、いくつかの追加手順が必要です。 zx は child_process に基づいており、引数をエスケープし、適切なデフォルトを提供します。 インストール npm i -g zx 必要な環境 Node.js >= 14.8.0 最上位レベルで await を使用できるようにするには、.mjs 拡張子を持つファイルにスクリプトを記述します。 zx スクリプトの先頭に次のシェバンを追加します。 #!/usr/bin/envzx です これで、次のようにスクリプトを実行できるようになります。 chmod +x ./script.mjs ./script.mjs または、zx 実行ファイル経由で: zx ./script.mjs すべての関数 ($、cd、fetch など) は、インポートなしで直接使用できます。 $`コマンド`child_process パッケージの spawn 関数を使用して、指定された文字列を実行し、ProcessPromise を返します。 count = parseInt($`ls -1 | wc -l` を待機) console.log(`ファイル数: ${count}`) たとえば、ファイルを並列にアップロードするには、次のようにします。 実行されたプログラムがゼロ以外の終了コードを返す場合、ProcessOutput がスローされます。 試す { $`exit 1` を待つ } キャッチ (p) { console.log(`終了コード: ${p.exitCode}`) console.log(`エラー: ${p.stderr}`) } ProcessPromise、以下はPromise TypeScriptのインターフェース定義です クラス ProcessPromise<T> は Promise<T> を拡張します { 読み取り専用 stdin: 書き込み可能 読み取り専用標準出力: 読み取り可能 読み取り専用stderr: 読み取り可能 読み取り専用終了コード: Promise<数値> パイプ(dest): ProcessPromise<T> } pipe() メソッドを使用して標準出力をリダイレクトできます。 $`cat file.txt`.pipe(process.stdout) を待機します。 パイプラインの詳細については、github.com/google/zx/b… をご覧ください。 ProcessOutput の Typescript インターフェース定義 クラス ProcessOutput { 読み取り専用 stdout: 文字列 読み取り専用 stderr: 文字列 読み取り専用終了コード: 数値 toString(): 文字列 } 関数: CD()現在の作業ディレクトリを変更する cd('/tmp') $`pwd` を待機 // /tmp を出力 フェッチ()node-fetch パッケージ。 resp = await fetch('http://wttr.in') を実行します。 (応答OK)の場合{ console.log(応答テキスト()を待つ) } 質問()readline パッケージ let bear = await question('どんなクマが一番いいですか? ') let token = await question('環境変数を選択してください: ', { 選択肢: Object.keys(process.env) }) 2番目のパラメータでは、タブの自動補完のオプションの配列を指定できます。 以下はインターフェース定義です 関数 question(query?: string, options?: QuestionOptions): Promise<string> QuestionOptions をタイプします。選択肢: 文字列[] } 寝る()setTimeout関数に基づく スリープを待つ(1000) スローしない()終了コードが 0 でない場合に例外をスローしないように $ の動作を変更します。 ts インターフェース定義 関数 nothrow<P>(p: P): P await nothrow($`grep something from-file`) // パイプライン内部: $`find ./examples -type f -print0` を待ちます .pipe(nothrow($`xargs -0 grep something`)) .pipe($`wc -l`) 以下のパッケージはインポートする必要がなく、直接使用できます。 チョークconsole.log(chalk.blue('Hello world!')) フェス次のような使い方も可能 'fs' から { promises as fs } をインポートします コンテンツ = fs.readFile('./package.json') を待機します。 オス$`cd ${os.homedir()} && mkdir example` を待機します 構成: $.シェル使用する bash を指定します。 $.shell = '/usr/bin/bash' $.引用コマンド置換時に特殊文字をエスケープするために使用される関数を指定します 使用されるデフォルトのパッケージは shq です。 知らせ: 2 つの変数 __filename と __dirname は commonjs にあります。 .mjs で終わる es6 モジュールを使用します。 ESM モジュールでは、Node.js は __filename および __dirname グローバル変数を提供しません。 このようなグローバル変数はスクリプトでは非常に便利なので、zx は .mjs ファイルで使用するためにこれらを提供します (zx 実行ファイルを使用する場合) Require は commonjs のモジュールインポートメソッドでもあります。 ESM モジュールには require() 関数が定義されていません。 zx は require() 関数を提供しているので、.mjs ファイルでのインポートで使用できます (zx 実行ファイルを使用する場合) 環境変数を渡すprocess.env.FOO = 'バー' $`echo $FOO` を待つ 配列を渡す値の配列が引数として $ に渡された場合、配列の項目は個別にエスケープされ、スペースで連結されます。 例: ファイルを[1,2,3]とします $`tar cz ${files}` を待機します $やその他の関数は明示的にインポートすることで使用できます #!/usr/bin/env ノード 'zx' から {$} をインポートします $`date` を待つ zxは.tsスクリプトを.mjsにコンパイルして実行することができます。 タイプスクリプトの例 要約するこれで、Node.js で bash スクリプトを作成する方法についての記事は終了です。Node.js で bash スクリプトを作成する方法についての詳細は、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Windows SSHサーバーを簡単に構築するためのいくつかの手順
>>: MySQL トリガー: 複数のトリガー操作の作成例の分析
1. mysql-8.0.21-winx64を解凍する2. 環境変数を設定し、アドレスをbinフォル...
目次1. 使用2. メッセージポップアップウィンドウが繰り返し表示される問題を解決する1. 使用Vu...
目次1. ログ関連サービス2. システム内の共通ログファイル1. ログ関連サービスCentOS 6....
ミニプログラムページ間で値を渡すみなさんこんばんは。こんばんはと言うのは、これを夜に書いたからです。...
この記事では、入力ボックスコンポーネントを手動で実装するための具体的なコードを参考までに紹介します。...
MVCC MVCC (Multi-Version Concurrency Control) は、マル...
セキュアターミナルMobaXterm_Personalをダウンロードまず、安全なターミナルをダウンロ...
/etc/fstabパーティション/ディスクを自動的にマウントし、マウントするパーティション/デバイ...
MySQLユーザー権限を表示する2つの方法を紹介します1. MySQL grantsコマンドを使用す...
Confluence は有料ですが、クラックして使用できます (購入が推奨され、正規版がサポートされ...
まず、Windows 64 ビット用の最新の MySQL 5.7.17 コミュニティ圧縮バージョンを...
目次1 Apacheの役割2 Apacheのインストール3. Apacheを有効にする4 Apach...
包括的なドキュメントgithubアドレスhttps://github.com/RocketChat/...
div で background-color と background-image を同時に設定する...
ログポイントベースのレプリケーション1. マスターデータベースとスレーブデータベースに専用のレプリケ...