これは、Chromium OSシェルであるcroshのホームページ/ドキュメントです。 あなたが今Croデバイスを使用している場合は、Ctrl+Alt+Tを押してcroshを起動することができるはずです。
実行するだけhelp
利用可能なコマンドに関する情報を取得し、より多くを発見します。
タブ補完を使用して、既存のコマンドをすばやく見つけることもできます。それは冒険です!
Chromium OS開発者向け
このセクションは、Chromium OSをハッキングする人々、特にcroshを変更/拡張する必要がある場合を対象としています。
セキュリティ警告
完全なセキュリティレビューなしに新しいモジュールをインストールしないでください。 Croshがロードする安全でないコードは、検証モードの人々が直接利用できるようになります。 これは、任意のコードを実行し、ユーザーの状態を混乱させるための簡単な攻撃ベクトルです。 私たちは、Croのセキュリティを弱体化させたくありません!あなたはレビュアーを探している場合は、を見てください。
あなたはレビュアーを探している場合は、を見てください。/所有者ファイル。
ファイルが存在する場所
CroshはシェルからRustに移行されています。 Croshはsrc/main.rsから実行を開始しますが、ほとんどのコマンドは高レベルモジュールのいずれかの独自のサブモジュールとして実装されています(例:base
dev
)。
メインのcrosh
スクリプトには、コアcroshロジックのレガシー実装が含まれていますが、他のレガシー関数はモジュールディレクトリにあります。 従来のバージョンのcroshは、crosh.sh
としてデバイスにインストールされます。
Source Repos
ボードに固有のモジュール、またはパッケージに非常に固有のモジュールは、通常、そのボードおよび/またはパッケージと一緒に使用する必要があ すべてのCroデバイスで常に利用可能な関数の場合、そのコードはこのリポジトリに保持する必要があります。あなたがわからない場合は、ちょうど尋ねます。
新しいコマンドの追加
最初に、新しいコマンドが使用する実装戦略を決定します。 戦略を選択する際には、どの権限と権限が必要かを知るのに役立ちます。 戦略を念頭に置いて、以下のさまざまな例をチェックしてください。
コマンドデザイン
croshシェルはブラウザと同じ環境(同じユーザー/グループ、同じLinux名前空間など)で実行されます。
コマンドデザイン
croshシェルはブラウザと同じ環境(同じユーザー/グループ、同じLinux名前空間など)..). したがって、croshで実行するツール、または取得しようとする情報は、chronos
ユーザーがアクセスできる必要があります。
しかし、croshが実際にツールを直接実行することはめったにありません。 代わりに、d-Busコールバックをdebugdデーモンに追加し、すべての要求をそれに送信する必要があります。 Debugdでアクセスを制御し、ツールをロックダウンすることができます。 次に、croshに存在する唯一のロジックは、D-Bus IPC呼び出しであり、それらのプログラムからの出力を表示します。 Debugdの議論はここでは範囲外なので、代わりにdebugdディレクトリをチェックしてください。
Examples
実装例:
- D-Bus method wrapper(debugd):base::verify_ro
D-Bus APIが既に計画されている場合、またはcroshに必要な権限または機能がない場合に使用します。 - External binary wrapper:base::ccd_pass
croshの機能を持つchronosとして実行するときに動作するコマンドを実装するコマンドラインツールが既にある場合に使用します。 - Rustで書かれたコマンド:base::arc
これは、余分な機能が必要ではなく、別のコマンドラインツールを持つことが正当化されない場合に最も適しています。
新しいコマンドを書くためのサンプルワークフローが以下に含まれています。
Module Setup
属するコマンドの適切なモジュールを選択します。 Devモードのコマンドの場合、これはdev
base
base
を使用しますが、それ以外の場合も同じ手順が適用されます。
次に、コマンド名を選択し、その名前のサブモジュールを作成し、それを親モジュールに登録します。 この例では、コマンドはverify_ro
src/base/verify_ro.rs
src/base/mod.rs
に追加する必要があります。
まず、サブモ次に、親モジュールsrc/base/mod.rs
のregister関数(以下で作成する)を呼び出す必要があります:これで、src/base/verify_ro.rs
ソースファイルを書き込む準備が整いました。 この最小限のソースファイルから開始し、croshがcargo build
:
use crate::dispatcher::Dispatcher;pub fn register(dispatcher: &mut Dispatcher) { dispatcher.register_command( Command::new( "verify_ro".to_string(), "TODO put usage here".to_string(), "TODO put description here".to_string(), ) .set_command_callback(Some(execute_verify_ro)), );}fn execute_verify_ro(_cmd: &Command, args: &Arguments) -> Result<(), dispatcher::Error> { unimplemented!();}
コマンド実装
でコンパイルされていることを確認します。
特権操作はCroshによって実行できないため(ただし、debugdまたは他の場所で実装する必要があります)、以下の例では、特にD-Busに焦点を当て、新しいCroshコ
debugdのD-Busインタフェースにはすでにdev-rust/system_apiで生成されたRustバインディングがあるので、バインディングとD-Bus接続は次のようにインポートできます。
use dbus::blocking::Connection;use system_api::client::OrgChromiumDebugd;
生成されたバインディングのソースコードを参照したい場合は、build_packagesを実行した後、次のパスを見てください。
/build/${BOARD}/usr/lib/cros_rust_registry/registry/system_api-*/src/bindings/client/
コマンド実装内では、D-bus接続を初期化する必要があります。 この例では、ブロッキング接続が使用されます。
let connection = Connection::new_system().map_err(|err| { error!("ERROR: Failed to get D-Bus connection: {}", err); dispatcher::Error::CommandReturnedError})?;
バス接続を使用して、目的のサービスへのインターフェイスを取得できます。
let conn_path = connection.with_proxy( "org.chromium.debugd", "/org/chromium/debugd", DEFAULT_DBUS_TIMEOUT,);
残りのメソッド呼び出しは、インポートされたトレイトsystem_api::client::OrgChromiumDebugd
system_api::client::OrgChromiumDebugd
let conn_path = connection.with_proxy( "org.chromium.debugd", "/org/chromium/debugd", DEFAULT_DBUS_TIMEOUT,);
conn_path
だから、d-busメソッドにマップするメンバー関数はconn_path
から呼び出すことができます。 たとえば、次のようにします。
conn_path .update_and_verify_fwon_usb_stop(handle) .map_err(|err| { println!("ERROR: Got unexpected result: {}", err); dispatcher::Error::CommandReturnedError })?;
これは基本をカバーしています。 Baseの実際のソースコードを見ると::verify_roでは、startメソッド呼び出し、watcher、およびstopメソッド呼び出しを使用して、より複雑な例を提供します。
コマンドヘルプ
デフォルトのヘルプ文字列は、コマンド名、使用文字列、説明文字列、およびdispatcher APIを介して登録されたオプションまたはフラ
または、バイナリのhelpオプションを呼び出すようなカスタムロジックを実行するために、コマンドを登録するときにヘルプコールバックを設定 例えば:
const EXECUTABLE: &str = "/usr/bin/vmc";pub fn register(dispatcher: &mut Dispatcher) { dispatcher.register_command( Command::new("vmc".to_string(), "".to_string(), "".to_string()) .set_command_callback(Some(execute_vmc)) .set_help_callback(vmc_help), );}fn vmc_help(_cmd: &Command, w: &mut dyn Write, _level: usize) { let mut sub = process::Command::new(EXECUTABLE) .arg("--help") .stdout(Stdio::piped()) .spawn() .unwrap(); if copy(&mut sub.stdout.take().unwrap(), w).is_err() { panic!(); } if sub.wait().is_err() { panic!(); }}
非推奨コマンド
croshコマンドを他のUI(chrome://pageなど)に置き換えたい場合、人々がそれを使用しようとした場合に友好的なメモを残して
# Set the vars to pass the unittests ...USAGE_storage_status=''HELP_storage_status=''# ... then unset them to hide the command from "help" output.unset USAGE_storage_status HELP_storage_statuscmd_storage_status() ( # TODO: Delete this after the R## release branch. echo "Removed. See storage_info section in chrome://system")
TODOコメントを追加して、人々がそれをクリーンアップしても大丈夫なときに将来知っていることを確認してください。
テスト
反復開発
デスクトップシステムで./crosh
を実行してサンプルシェルを取得できます。 ここで基本的な相互作用(引数の解析など)をすばやくテストしたり、ヘルプ出力を確認したりできます。 多くのcroshコマンドが(D-Bus経由で)通信することを期待しているCrOSサービスにアクセスできないため、これらのコマンドは失敗します。devモードモジュールをロードする場合は、./crosh --dev
./dev.d/
./crosh --removable
を使用できます。
Unittests
単体テストを実行するには、croshフォルダでcargo test --workspace
emege-${BOARD} crosh && FEATURES=test emerge-${BOARD}
./run_tests.sh
レガシー unittestランナーは、基本的なスタ シェルコードへの変更に対してそれを実行します!
将来の仕事
誰もがこれらのアイデアをピックアップし、それらを実装しようとすること自由に感じる必要があります:)。
- 代わりに実装されている残りのコマンドをdebugd呼び出しに移動して、D-Busを介して実行できるようにします。
- 制限されたサンドボックス(namespaces/seccomp/など)でcrosh自体を実行します。..). すべてのコマンドがIPC経由で実行されると、privsを保持する必要はありません。 ただし、devモードに依存する可能性があるため、
shell
を中断しません。 - 追加のレガシーシェルコマンドをRustに移行します。 これは、コマンドをdebugdに移行するのと同時に行うこともできます。
レガシー Croshドキュメント
Croshはもともとシェルで書かれていました。 この記事を書いている時点では、多くのコマンドはまだシェルに残っており、まだRust croshに移植されていません。 この文書は、これらのコマンドの保守のためにここに保管されています。
コマンドAPI
すべてのコマンドに対して、2つの変数と1つの関数を定義します。 Croshは独自のランタイム環境を検査してそれらを検出するため、新しいコマンドをどこにでも登録する必要はありません。新しいfoo
コマンドを登録する方法は次のとおりです。
# A short description of arguments that this command accepts.USAGE_foo='<some args>'HELP_foo=' Extended description of this command.'# Not required, but lets crosh detect if the foo program is available in the# current system (e.g. the package is not installed on all devices). If it# isn't available, crosh will automatically display an error message and never# call cmd_foo.EXEC_foo='/full/path/to/program'cmd_foo() ( # Implementation for the foo command. # You should validate $# and "$@" and process them first. # For invalid args, call the help function with an error message # before returning non-zero. ...foo code goes here!...)
新しいコマンドをどのように構造化するかの詳細については、以下の設計セクションを参照してください。
Command Help
croshコマンドが処理を行うために外部プログラムを呼び出すだけで、そのプログラムがすでに使用状況の詳細を提供している場合は、 このシナリオを処理するには、それぞれの呼び出しを行うhelp_foo
関数を定義します。p>
# Set the help string so crosh can discover us automatically.HELP_foo=''cmd_foo() ( ...)help_foo() ( /some/command --help)
まだHELP_foo
を設定していることに注意してください。 これは、croshが自動的に私たちを発見し、関連するユーザー直面リストに表示できるようにするために必要です(help_advanced
USAGE_foo
help_foo
関数はそれを行います。
Hiding Commands
コマンドがまだ”プライムタイム”の準備ができていない場合は、初期のテストのためにcroshに表示したいかもしれませんが、help
出力に表示しないでください(もちろん、コードはすべて公開されているので、実際のソースを読んでいる人は誰でも見つけることができます)。 ここでは、それを行う方法です。p>
# Set the vars to pass the unittests ...USAGE_vmc=''HELP_vmc=''# ... then unset them to hide the command from "help" output.unset USAGE_vmc HELP_vmccmd_vmc() ( ...)