CLIを構築するときにargv、オプション、環境変数、stdin、stdout、およびstderrに許可されるルールはありますか?

CLIを構築するときにargv、オプション、環境変数、stdin、stdout、およびstderrに許可されるルールはありますか?

私はコマンドラインアプリケーションがどれほど簡単かについて話す傾向があります。一般的に、私は「彼らは標準入力から読んで、標準出力と標準エラーに書きます。それから次の図を描きました」と言います。

ここに画像の説明を入力してください。

しかし、それが実際に物語の終わりではないと考え始めました。コマンドラインアプリケーションは標準入力から読み込み、標準エラーと標準出力に書き込みます。

  • /etc設定ファイルを読む( 、~などの複数の場所から.
  • 環境変数を読む
  • コマンドラインスイッチを読む
  • コマンドラインフラグを読む
  • コマンドラインパラメータを読む
  • 終了ステータスの設定

コマンドラインアプリケーションは次のように表示されます。

ここに画像の説明を入力してください。

客観的に言えば、これは単純なstdin、stdout、stderrよりも複雑です。

私は一日中コマンドラインアプリケーションを使用します。時間が経つにつれて、私は彼らに対する自分の意見や直感を発展させました。

  • 基準 - 通常パラメータ以外のデータ(使用しない限りxargs
  • stdout - 製品、好ましくは列形式データ
  • stderr - 問題が発生したときにエラーまたはエラーメッセージを記録するために使用されます。
  • 終了ステータス - 神聖、0は成功、1は失敗(または他の種類の失敗)を意味します。
  • パラメータ - 重要ですが、標準とは異なる読み方
  • フラグ - パラメータに似ていますが、それほど重要ではありません
  • スイッチ - フラグに似ていますが、オンまたはオフにすることができます。
  • 環境変数 - パラメータと少し似ていますが、それらの間には哲学的な違いがあります。
  • 設定ファイル - 環境変数と少し似ているため、スイッチやフラグを制御できますが、それをバージョン管理に保ち、通常はスイッチとフラグの残念な組み合わせを使用する必要がないようにしたり、誰にでも表示したりできます。ドットファイル?

このガイドは、私が使用するさまざまなコマンドラインツールに適用される傾向があります。しかし、他の人が使用できるようにするときに参考になれば幸いです。

たとえば、次はRubyで書かれたコマンドラインアプリケーションです。

#!/usr/bin/env ruby
# somecli

require 'optparse'
require 'yaml'

options = {}

etc_config = File.join('etc', 'somecli')
if File.exist? etc_config
  options.merge! YAML.load_file(etc_config)
end

home_config = File.join(ENV['HOME'], '.somecli')
if File.exist? home_config
  options.merge! YAML.load_file(home_config)
end

current_working_directory_config = '.somecli'
if File.exist? current_working_directory_config
  options.merge! YAML.load_file(current_working_directory_config)
end

OptionParser.new do |opts|
  opts.on("-s", "--[no-]switch") do |s|
    options[:switch] = s
  end
  opts.on("-a", "--[no-]another-switch") do |as|
    options[:'another-switch'] = as
  end
  opts.on("-y", "--[no-]yet-another-switch") do |yas|
    options[:'yet-another-switch'] = yas
  end
  opts.on("-y", "--[no-]even-yet-another-switch") do |eyas|
    options[:'even-yet-another-switch'] = eyas
  end
  opts.on("--flag FLAG") do |f|
    options[:flag] = f
  end
end.parse!

puts "ARGV=#{ARGV.inspect}"
puts "options=#{options.inspect}"
puts "ENV['cats']=#{ENV['cats'].inspect}"
unless STDIN.tty?
  puts "STDIN.read=#{STDIN.read.inspect}"
end
$stderr.puts "stderr: hello world!"
$stdout.puts "stdout: hello world!"
exit 0

実行すると、次のようになります。

echo -n foo bar baz | ./somecli -s -f flap jacks; echo $?
ARGV=["jacks"]
options={:"another-switch"=>true, :"even-yet-another-switch"=>true, :switch=>true, :flag=>"flap"}
ENV['cats']="flapjacks"
STDIN.read="foo bar baz"
stderr: hello world!
stdout: hello world!
0

入出力ルールとデザインの決定を導くためのより正式な文書へのリンクを追加情報に提供したいと思います。

わかりましたPOSIXシステムに何をインストールするかを決定するために使用できる一般的なユーティリティがあります。ただし、コマンドラインアプリケーションを構築するときは、次の2つを知りたいと思います。

  1. 私が見逃したコマンドラインプログラムに入力を取得する他の一般的な方法はありますか?
  2. さまざまな入力と出力を構成する方法に関する規則に関する権威ある文書はありますか?

答え1

コマンドラインユーティリティに関するいくつかの一般的なガイドラインは、POSIX.1 / Single UNIX仕様に文書化されています。

バラよりセクション12.2:ユーティリティ構文ガイド

答え2

常識以外には何の習慣もないと思います。

入出力方法について、または一般的に言えば、通信する方法、あなたは1つの方法について言及したが、それらのいくつかだけ言及した。ファイルを読み書きすることです。 (設定ファイルを読むと言った、または一般的にファイル記述子.)

ファイルと同様に、パイプとソケットがあります。例えば。方法と見なすことができるTCP、UDP、またはUnixソケットプロセス間通信(IPC)。他のタイプのIPCは次のとおりです。

  • 共有メモリとマッピングされたメモリ
  • シグナル
  • シグナル
  • Dバス

関連情報