detta är hemsidan/dokumentationen för crosh, Chromium OS shell. Om du är på en CrOS-enhet just nu borde du kunna starta crosh genom att trycka Ctrl+Alt+T. Om du inte är på CrOS, så är det troligt att det inte kommer att göra något användbart :).
kör bara help
för att få information om tillgängliga kommandon och upptäcka mer.
Du kan också använda flikkomplettering för att snabbt hitta befintliga kommandon.
det är ett äventyr!
- för Chromium OS-utvecklare
- Säkerhetsvarning
- där filer bor
- Källrepos
- lägga till nya kommandon
- Kommandodesign
- exempel
- Modulinställning
- Kommandoimplementering
- Kommandohjälp
- avskrivande kommandon
- testning
- iterativ utveckling
- Unittests
- framtida arbete
- Legacy Crosh dokumentation
- Command API
- Kommandohjälp
- dölj kommandon
för Chromium OS-utvecklare
detta avsnitt är avsett för personer som hackar på Chromium OS, särskilt när de behöver ändra / förlänga crosh.
Säkerhetsvarning
Installera inte nya moduler utan fullständig säkerhetsgranskning. Varje osäker kod som crosh laddar kommer att vara direkt tillgänglig för personer i verifierat läge. Det är en enkel attackvektor för att köra godtycklig kod och röra med användarens tillstånd. Vi vill inte undergräva CrOS säkerhet!
om du letar efter granskare, titta på ./ Ägare fil.
där filer bor
Crosh migreras från skal till rost. Crosh börjar köra från src / main. rs men de flesta kommandon implementeras som sin egen delmodul av en av högnivåmodulerna (t.ex. base
eller dev
).
huvudskriptetcrosh
innehåller äldre implementering av core crosh logic medan andra äldre funktioner bor i modulkataloger. Den äldre versionen av crosh är installerad på enheten som crosh.sh
.
Källrepos
moduler som är specifika för ett kort, eller starkt specifikt för ett paket, bör i allmänhet leva med det kortet och / eller paketet. För funktioner som alltid är tillgängliga på alla CrOS-enheter bör den koden förvaras i denna repo.
om du är osäker, fråga bara på [email protected].
lägga till nya kommandon
bestäm först vilken implementeringsstrategi det nya kommandot ska använda. När du väljer en strategi hjälper det att veta vilka behörigheter och privilegier som behövs. Med strategin i åtanke, kolla in de olika exemplen nedan.
Kommandodesign
crosh-skalet körs i samma miljö som webbläsaren (samma användare / grupp, samma Linux-namnområden etc…). Så alla verktyg du kör i crosh, eller information du försöker skaffa, måste vara tillgängliga förchronos
användaren.
men vi vill sällan crosh att faktiskt utföra verktyg direkt. Istället bör du lägga till D-Bus callbacks till debugd-demonen och skicka alla förfrågningar till den. Vi kan bättre kontrollera åtkomst i debugd och låsa verktyg ner. Då är den enda logiken som finns i crosh ett D-Bus IPC-samtal och visar sedan utdata från dessa program. Diskussionen om debugd är out of scope här, så kolla in debugd-katalogen istället.
exempel
exempel implementeringar:
- D-Bus method wrapper (debugd): base::verify_ro
Använd detta när ett D-Bus API redan är planerat eller crosh saknar nödvändiga behörigheter eller funktioner. - extern binär omslag: base:: ccd_pass
Använd detta när det redan finns ett kommandoradsverktyg som implementerar kommandot som fungerar när det körs som chronos med croshs funktioner. - kommando skrivet i Rust: bas::arc
detta passar bäst för fall där extra funktioner inte behövs och att ha ett separat kommandoradsverktyg är inte motiverat.
ett exempelarbetsflöde ingår nedan för att skriva ett nytt kommando.
Modulinställning
Välj en lämplig modul för kommandot att tillhöra. För dev-lägeskommandon kommer detta att vara dev
, de flesta andra kommandon kommer att tillhöra base
. Detta exempel använderbase
som modul, men samma steg bör fortfarande gälla i andra fall.
välj sedan ett kommandonamn, skapa en undermodul med det namnet och registrera det med den överordnade modulen. I det här exemplet är kommandot verify_ro
, så den nya källfilen är src/base/verify_ro.rs
och två rader måste läggas till src/base/mod.rs
:
först måste submodulen importeras:
mod verify_ro;
För det andra måste registerfunktionen (som ska skapas nedan) anropas av registerfunktionen i överordnade modulen src/base/mod.rs
:
pub fn register(dispatcher: &mut Dispatcher) { ... verify_ro::register(dispatcher); ...}
nu ärsrc/base/verify_ro.rs
källfilen redo att skrivas. Börja med den här minimala källfilen och kontrollera att crosh kompilerar medcargo 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!();}
Kommandoimplementering
detta förutsätter att ovanstående instruktioner redan är färdiga.eftersom privilegierade operationer inte kan utföras av Crosh (men bör implementeras i debugd eller var som helst) fokuserar exemplet nedan särskilt på D-Bus och antar att det finns en befintlig D-Bus-metod som måste anropas från ett nytt Crosh-kommando.Observera att debugds D-Bus-gränssnitt redan har Rostbindningar genererade genom Dev-rust/system_api, så bindningarna och D-Bus-anslutningen kan importeras med:
use dbus::blocking::Connection;use system_api::client::OrgChromiumDebugd;
om du vill bläddra i källkoden för de genererade bindningarna, efter att ha kört build_packages, ta en titt på följande sökväg:
/build/${BOARD}/usr/lib/cros_rust_registry/registry/system_api-*/src/bindings/client/
inuti kommandoimplementeringen måste en D-Bus-anslutning initialiseras. En blockeringsanslutning används i det här exemplet.
let connection = Connection::new_system().map_err(|err| { error!("ERROR: Failed to get D-Bus connection: {}", err); dispatcher::Error::CommandReturnedError})?;
bussanslutningen kan sedan användas för att få ett gränssnitt till önskad tjänst, vilket är debugd i detta fall:
let conn_path = connection.with_proxy( "org.chromium.debugd", "/org/chromium/debugd", DEFAULT_DBUS_TIMEOUT,);
resten av metodsamtalet använder det faktum att den importerade egenskapen system_api::client::OrgChromiumDebugd
implementeras för conn_path
så medlemsfunktionerna som kartlägger till D-Bus-metoder kan ringas från conn_path
. Till exempel:
conn_path .update_and_verify_fwon_usb_stop(handle) .map_err(|err| { println!("ERROR: Got unexpected result: {}", err); dispatcher::Error::CommandReturnedError })?;
detta täcker grunderna. Om du tittar på den faktiska källkoden för base::verify_ro, det ger ett mer komplicerat exempel med ett startmetodsamtal, en watcher och ett stoppmetodsamtal.
Kommandohjälp
standardhjälpssträngarna fylls i med kommandonamn, användningssträng, beskrivningssträng och eventuella alternativ eller flaggor som är registrerade via avsändarens API.
Alternativt kan en hjälpuppringning ställas in när du registrerar kommandot för att utföra Anpassad logik som att åberopa hjälpalternativet för en binär. Exempelvis:
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!(); }}
avskrivande kommandon
Om du vill ersätta ett crosh-kommando med något annat användargränssnitt (som en chrome:// sida), och du vill avskriva kommandot graciöst genom att lämna en vänlig anteckning om folk försöker använda den, här är formuläret.
# 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")
se till att du lägger till todo-kommentaren så att folk vet i framtiden när det är OK att städa upp det.
testning
iterativ utveckling
Du kan köra ./crosh
på ditt skrivbordssystem för att få ett provskal. Du kan snabbt testa grundläggande interaktioner (som argumentparsning) här, eller kontrollera hjälputmatningen. Du har inte tillgång till CrOS-tjänsterna som många crosh-kommandon förväntar sig att prata med (Via D-Bus), så dessa kommandon misslyckas.
Om du vill ladda dev mode-moduler kan du använda ./crosh --dev
. Det laddar bara lokala moduler (./dev.d/
), så om din modul bor någon annanstans kan du kopiera den här tillfälligt.
På samma sätt kan du använda ./crosh --removable
om du vill ladda flyttbara enhetsmoduler.
Unittests
för att köra enhetstesterna, ring antingen cargo test --workspace
I crosh-mappen eller kör emege-${BOARD} crosh && FEATURES=test emerge-${BOARD}
./run_tests.sh
legacy unittest runner utför en massa grundläggande stil-och ljudkontroller. Kör det mot eventuella ändringar i skalkoden!
framtida arbete
vem som helst borde gärna hämta dessa tankar och försöka implementera dem :).
- flytta eventuella återstående kommandon som implementeras på plats för att felsöka samtal så att de kan göras över D-Bus.
- kör crosh själv i en begränsad sandlåda(namnområden / seccomp / etc…). När alla kommandon görs via IPC, det finns ingen anledning att hålla privs. Kan göra det beroende av dev-läge men så bryter vi inte
shell
. - migrera ytterligare äldre skalkommandon över till Rust. Detta kan också göras samtidigt som du migrerar ett kommando över till debugd.
Legacy Crosh dokumentation
Crosh skrevs ursprungligen med skal. I skrivande stund är många av kommandona fortfarande kvar i skalet och har ännu inte portats över till Rust crosh. Denna dokumentation hålls här för underhåll av dessa kommandon.
Command API
för varje kommando definierar du två variabler och en funktion. Det finns inget behov av att registrera de nya kommandona var som helst eftersom crosh kommer att inspektera sin egen runtime-miljö för att upptäcka dem.
Så här registrerar du ett nytt foo
kommando.
# 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!...)
se avsnittet design nedan för mer information om vad och hur man strukturerar det nya kommandot.
Kommandohjälp
Om ditt crosh-kommando helt enkelt ropar till ett externt program för att göra behandlingen, och det programmet erbjuder redan användningsinformation, vill du förmodligen inte behöva duplicera saker. Du kan hantera detta scenario genom att definiera en help_foo
funktion som gör respektive samtal.
# Set the help string so crosh can discover us automatically.HELP_foo=''cmd_foo() ( ...)help_foo() ( /some/command --help)
Observera att vi fortfarande ställer in HELP_foo
. Detta behövs så att crosh kan upptäcka oss automatiskt och visa oss i de relevanta användarlistorna (som kommandot help_advanced
). Vi behöver inte ställa in USAGE_foo
men eftersom funktionen help_foo
gör det för oss.
dölj kommandon
om ett kommando ännu inte är klart för ”prime time” kanske du vill ha det i crosh för tidig testning, men inte ha det i help
utgång där användare enkelt kan upptäcka det (naturligtvis är koden all offentlig, så alla som läser den faktiska källan kan hitta den). Så här gör du det.
# 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() ( ...)