aceasta este pagina de pornire / documentația pentru crosh, Chromium OS shell. Dacă sunteți pe un dispozitiv CrOS chiar acum, ar trebui să puteți lansa crosh apăsând Ctrl+Alt+T. Dacă nu sunteți pe CrOS, atunci cel mai probabil că nu va face nimic util :).
trebuie doar să rulați help
pentru a obține informații despre comenzile disponibile și pentru a descoperi mai multe.
de asemenea, puteți utiliza completarea filei pentru a găsi rapid comenzile existente.
este o aventură!
- pentru Chromium OS Developers
- avertisment de securitate
- unde trăiesc fișierele
- repo-uri sursă
- adăugarea de noi comenzi
- design de comandă
- Exemple
- modul de configurare
- implementarea comenzii
- Command Help
- deprecierea comenzilor
- testare
- dezvoltare iterativă
- Unittests
- munca viitoare
- Legacy Crosh documentație
- comanda API
- ajutor comandă
- ascunderea comenzilor
pentru Chromium OS Developers
această secțiune este destinată persoanelor care piratează pe Chromium OS, mai ales atunci când trebuie să modifice/extindă crosh.
avertisment de securitate
vă rugăm să nu instalați module noi fără revizuire completă de securitate. Orice cod nesigur pe care îl încarcă crosh va fi disponibil direct persoanelor în modul verificat. Acesta este un vector de atac ușor pentru a rula cod arbitrar și mizerie cu starea utilizatorului. Nu vrem să subminăm securitatea CrOS!
Dacă sunteți în căutarea pentru recenzenți, uita-te la ./ Proprietarii fișier.
unde trăiesc fișierele
Crosh este migrat de la shell la Rust. Crosh începe executarea de la src / main. rs, dar majoritatea comenzilor sunt implementate ca submodul propriu al unuia dintre modulele de nivel înalt (de exemplu base
sau dev
).
scriptul principalcrosh
conține implementarea moștenită a logicii crosh de bază, în timp ce alte funcții moștenite trăiesc în directoarele modulelor. Versiunea veche a crosh este instalată pe dispozitiv ca crosh.sh
.
repo-uri sursă
modulele care sunt specifice unei plăci sau foarte specifice unui pachet ar trebui să trăiască în general cu acea placă și / sau pachet. Pentru funcțiile care sunt întotdeauna disponibile pe toate dispozitivele CrOS, acest cod trebuie păstrat în acest repo.
dacă nu sunteți sigur, întrebați [email protected].
adăugarea de noi comenzi
Mai întâi determinați ce strategie de implementare va folosi noua comandă. Când selectați o strategie, vă ajută să știți ce permisiuni și privilegii sunt necesare. Având în vedere strategia, consultați diferitele exemple de mai jos.
design de comandă
shell-ul crosh rulează în același mediu ca browserul (același utilizator / grup, aceleași spații de nume Linux etc…). Deci, orice instrumente pe care le rulați în crosh sau informații pe care încercați să le achiziționați trebuie să fie accesibile utilizatorului chronos
.
cu toate acestea, rareori dorim ca crosh să execute direct instrumentele. În schimb, ar trebui să adăugați apeluri D-Bus la demonul debugd și să trimiteți toate solicitările către acesta. Putem controla mai bine accesul în debugd și blocați instrumentele. Apoi, singura logică care există în crosh este un apel IPC D-Bus și apoi afișează ieșirea din aceste programe. Discuția despre debugd este în afara domeniului de aplicare aici, așa că consultați în schimb directorul debugd.
Exemple
exemplu implementări:
- D-Bus metoda wrapper (debugd): base::verify_ro
utilizați acest lucru atunci când un API D-Bus este deja planificat sau crosh nu are permisiunile sau capacitățile necesare. - extern binar wrapper: base::ccd_pass
utilizați acest lucru atunci când există deja un instrument de linie de comandă care implementează comanda care funcționează atunci când rula ca chronos cu capacitățile de crosh. - comandă scrisă în Rust: base::arc
acest lucru este cel mai potrivit pentru cazurile în care nu sunt necesare capacități suplimentare și nu este justificat să aveți un instrument separat de linie de comandă.
un flux de lucru eșantion este inclus mai jos pentru scrierea unei noi comenzi.
modul de configurare
alege un modul adecvat pentru comanda să aparțină. Pentru comenzile din modul dev aceasta va fi dev
, majoritatea celorlalte comenzi vor aparținebase
. Acest exemplu va folosi base
ca modul, dar aceiași pași ar trebui să se aplice în continuare în alte cazuri.
apoi alegeți un nume de comandă, creați un sub-modul cu acel nume și înregistrați-l la modulul părinte. Pentru acest exemplu comanda este verify_ro
, deci noul fișier sursă este src/base/verify_ro.rs
și două linii trebuie adăugate la src/base/mod.rs
:
în primul rând, submodul trebuie importat:
mod verify_ro;
În al doilea rând, funcția de înregistrare (care urmează să fie creată mai jos) trebuie să fie apelată de funcția de înregistrare din modulul părinte src/base/mod.rs
:
pub fn register(dispatcher: &mut Dispatcher) { ... verify_ro::register(dispatcher); ...}
acumsrc/base/verify_ro.rs
fișierul sursă este gata pentru a fi scris. Începeți cu acest fișier sursă minim și verificați dacă crosh compilează cucargo 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!();}
implementarea comenzii
aceasta presupune că instrucțiunile de mai sus sunt deja complete.
deoarece operațiunile privilegiate nu pot fi executate de Crosh (dar ar trebui implementate în debugd sau oriunde altundeva), exemplul de mai jos se concentrează în special pe D-Bus și presupune că există o metodă D-Bus existentă care trebuie apelată dintr-o nouă comandă Crosh.
rețineți că interfața D-Bus debugd are deja legături de rugină generate prin dev-rust/system_api, astfel încât legăturile și conexiunea D-Bus pot fi importate cu:
use dbus::blocking::Connection;use system_api::client::OrgChromiumDebugd;
Dacă doriți să răsfoiți codul sursă al legăturilor generate, după rularea build_packages, aruncați o privire la următoarea cale:
/build/${BOARD}/usr/lib/cros_rust_registry/registry/system_api-*/src/bindings/client/
în implementarea comenzii trebuie inițializată o conexiune D-Bus. O conexiune de blocare este utilizată în acest exemplu.
let connection = Connection::new_system().map_err(|err| { error!("ERROR: Failed to get D-Bus connection: {}", err); dispatcher::Error::CommandReturnedError})?;
conexiunea de autobuz poate fi apoi folosit pentru a obține o interfață la serviciul dorit, care este depanat în acest caz:
let conn_path = connection.with_proxy( "org.chromium.debugd", "/org/chromium/debugd", DEFAULT_DBUS_TIMEOUT,);
restul apelului metoda utilizează faptul că trasatura importat system_api::client::OrgChromiumDebugd
este implementat pentru
let conn_path = connection.with_proxy( "org.chromium.debugd", "/org/chromium/debugd", DEFAULT_DBUS_TIMEOUT,);
conn_path
deci funcțiile membre care mapează la metodele D-Bus pot fi apelate de la conn_path
. De exemplu:
conn_path .update_and_verify_fwon_usb_stop(handle) .map_err(|err| { println!("ERROR: Got unexpected result: {}", err); dispatcher::Error::CommandReturnedError })?;
aceasta acoperă elementele de bază. Dacă te uiți la codul sursă real pentru bază::verify_ro, acesta oferă un exemplu mai complicat, cu un apel metodă de pornire, un observator, și un apel metodă de oprire.
Command Help
șirurile de ajutor implicite sunt populate folosind numele comenzii, șirul de utilizare, șirul de descriere și orice opțiuni sau steaguri înregistrate prin API-ul dispecer.
alternativ, un apel invers de ajutor poate fi setat la înregistrarea comenzii pentru a efectua o logică personalizată, cum ar fi invocarea opțiunii de ajutor a unui binar. De exemplu:
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!(); }}
deprecierea comenzilor
Dacă doriți să înlocuiți o comandă crosh cu o altă interfață (cum ar fi o pagină chrome://) și doriți să depreciați comanda cu grație lăsând în urmă o notă prietenoasă dacă oamenii încearcă să o folosească, iată formularul.
# 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")
asigurați-vă că adăugați comentariul TODO, astfel încât oamenii să știe în viitor când este OK să-l curețe.
testare
dezvoltare iterativă
puteți rula./crosh
pe sistemul desktop pentru a obține un shell eșantion. Puteți testa rapid interacțiunile de bază (cum ar fi analiza argumentelor) aici sau puteți verifica ieșirea de ajutor. Nu veți avea acces la serviciile CrOS cu care multe comenzi crosh se așteaptă să vorbească (prin D-Bus), astfel încât aceste comenzi vor eșua.
Dacă doriți să încărcați Module Modul dev, puteți utiliza./crosh --dev
. Acesta va încărca numai module locale (./dev.d/
), deci dacă modulul dvs. locuiește în altă parte, îl puteți copia aici temporar.
în mod similar, dacă doriți să încărcați module de dispozitive detașabile, puteți utiliza./crosh --removable
.
Unittests
pentru a rula testele unitare fie apelațicargo test --workspace
în folderul crosh, fie rulațiemege-${BOARD} crosh && FEATURES=test emerge-${BOARD}
./run_tests.sh
Legacy unittest runner efectuează o grămadă de verificări de bază ale stilului și solidității. Rulați-l împotriva oricăror modificări ale codului shell!
munca viitoare
oricine ar trebui să se simtă liber pentru a ridica aceste idei și să încerce să le pună în aplicare :).
- mutați toate comenzile rămase care sunt implementate în loc pentru a depana apelurile, astfel încât acestea să poată fi efectuate prin D-Bus.
- rulați crosh în sine într-un sandbox restricționat (spații de nume/seccomp/etc…). Odată ce toate comenzile sunt efectuate prin IPC, nu este nevoie să păstrați privs. S-ar putea face dependent de modul dev, deși așa că nu rupe
shell
. - migra comenzi suplimentare Shell legacy pe la Rust. Acest lucru se poate face și în același timp cu migrarea unei comenzi către debugd.
Legacy Crosh documentație
Crosh a fost scris inițial în coajă. La momentul scrierii multe dintre comenzile sunt încă rămân în coajă și nu au fost încă să fie portate pe rugina crosh. Această documentație este păstrată aici pentru întreținerea acestor comenzi.
comanda API
pentru fiecare comandă, definiți două variabile și o funcție. Nu este nevoie să înregistrați noile comenzi oriunde, deoarece crosh își va inspecta propriul mediu de rulare pentru a le descoperi.
Iată cum ați înregistra o nouă comandă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!...)
consultați secțiunea de proiectare de mai jos pentru mai multe detalii despre ce și cum să structurați noua comandă.
ajutor comandă
dacă comanda crosh pur și simplu solicită la un program extern pentru a face procesarea, și că programul oferă deja detalii de Utilizare, probabil că nu doriți să aibă de a duplica lucruri. Puteți gestiona acest scenariu definind o funcție help_foo
care efectuează apelul respectiv.
# Set the help string so crosh can discover us automatically.HELP_foo=''cmd_foo() ( ...)help_foo() ( /some/command --help)
rețineți că încă setămHELP_foo
. Acest lucru este necesar pentru ca crosh să ne poată descoperi automat și să ne afișeze în listele relevante cu care se confruntă utilizatorul (cum ar fi comanda help_advanced
). Nu trebuie să setăm USAGE_foo
deși funcțiahelp_foo
face asta pentru noi.
ascunderea comenzilor
dacă o comandă nu este încă pregătită pentru „prime time”, s-ar putea să doriți să o aveți în crosh pentru testarea timpurie, dar să nu apară înhelp
ieșire unde utilizatorii o pot descoperi cu ușurință (desigur, codul este public, astfel încât oricine citește sursa reală o poate găsi). Iată cum o faci.
# 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() ( ...)