Crosh — the Chromium OS shell

This is the homepage / documentation for the crosh, the Chromium OS shell. Se você está em um dispositivo CrOS agora, você deve ser capaz de lançar crosh, carregando em Ctrl+Alt+T. Se você não estiver em CrOS, então muito provavelmente isso não fará nada de útil :).

apenas execute help para obter informações sobre os comandos disponíveis e descobrir mais.

pode também usar a completação de páginas para encontrar rapidamente os comandos existentes.é uma aventura!

para os desenvolvedores de crómio OS

Esta seção é destinada a pessoas que hackeiam crómio OS, especialmente quando eles precisam modificar / estender crosh.

Aviso de segurança

Por favor não instale novos módulos sem uma revisão completa da segurança. Qualquer código inseguro que carrega Cros estará diretamente disponível para as pessoas em modo verificado. É um vetor de ataque fácil para executar código arbitrário e mexer com o estado do Usuário. Não queremos minar a segurança do CrOS!

Se você está procurando revisores, olhe para o ./ OWNERS file.

Where Files Live

Crosh is being migrated from shell to Rust. O Crosh começa a executar a partir do src / main. rs, mas a maioria dos comandos são implementados como seu próprio submódulo de um dos módulos de alto nível (por exemplo, base ou dev).

the maincrosh script contains the legacy implementation of core crosh logic while other legacy functions live in module directories. A versão legada do crosh é instalada no dispositivo como crosh.sh.os Repos de código

módulos que são específicos de uma placa, ou fortemente específicos de um pacote, devem geralmente viver com essa placa e/ou pacote. Para funções que estão sempre disponíveis em todos os dispositivos CrOS, esse código deve ser mantido neste repo.se não tem a certeza, basta perguntar [email protected].

adicionando novos comandos

primeiro determine qual a estratégia de implementação que o novo comando irá usar. Ao selecionar uma estratégia, ele ajuda a saber quais permissões e privilégios são necessários. Com a estratégia em mente, confira os vários exemplos abaixo.

desenho de comandos

a linha de comandos crosh é executada no mesmo ambiente que o navegador (mesmo Utilizador/grupo, mesmos espaços de nomes Linux, etc…). Por isso, quaisquer ferramentas que execute no crosh, ou informações que tente adquirir, devem estar acessíveis ao utilizador chronos.

no entanto, raramente queremos que o crosh execute as ferramentas directamente. Em vez disso, deverá adicionar chamadas de D-Bus ao servidor de depuração e enviar todos os pedidos para ele. Podemos controlar melhor o acesso em debugd e bloquear as ferramentas. Então a única lógica que existe no crosh é uma chamada de D-Bus IPC e, em seguida, exibe a saída desses programas. A discussão do debugd está fora do escopo aqui, por isso verifique a pasta de depuração em vez disso.

Examples

Example implementations:

  • D-Bus method wrapper( debugd): base:: verify_ro
    Use isto quando uma API de D-Bus já está planeada ou crosh não tem as permissões ou capacidades necessárias.
  • binário Externo wrapper: base::ccd_pass
    Use isso quando já existe uma ferramenta de linha de comando que implementa o comando que funciona quando executado como chronos, com as capacidades de crosh.comando
  • escrito em Rust: base::arc
    Este é o mais adequado para casos em que capacidades extras não são necessárias e ter uma ferramenta de linha de comando separada não é justificado.

um fluxo de trabalho de amostra é incluído abaixo para escrever um novo comando.

configuração do módulo

escolha um módulo apropriado para o comando a pertencer. Para comandos do modo dev este será dev, a maioria dos outros comandos pertencerão a base. Este exemplo irá usar base como o módulo, mas os mesmos passos ainda devem ser aplicados em outros casos.

em seguida, escolher um nome de comando, Criar um sub módulo com esse nome, e registrá-lo com o módulo pai. Para este exemplo, o comando é verify_ro, para que o novo arquivo de origem é src/base/verify_ro.rs e duas linhas precisam ser adicionados ao src/base/mod.rs:

Primeiro, o submódulo precisa ser importado:

mod verify_ro;

Segundo a função de registro (a ser criado abaixo) precisa ser chamado a função de registro no módulo principal src/base/mod.rs:

Now thesrc/base/verify_ro.rs source file is ready to be written. Comece com este ficheiro de código mínimo e verifique se o crosh compila com 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!();}

implementação de comandos

isto assume que as instruções acima já estão completas.

Uma vez que as operações privilegiadas não podem ser executadas pelo Crosh (mas devem ser implementadas no debugd ou em qualquer outro lugar), o exemplo abaixo foca em D-Bus em particular e assume que existe um método D-Bus existente que precisa ser chamado a partir de um novo comando Crosh.

Note que debugd da interface de D-Bus já tem Ferrugem ligações geradas através dev-ferrugem/system_api, assim, as ligações e o D-Bus de conexão podem ser importados com:

use dbus::blocking::Connection;use system_api::client::OrgChromiumDebugd;

Se você deseja procurar o código-fonte do gerada ligações, após a execução build_packages, dê uma olhada no seguinte caminho:

/build/${BOARD}/usr/lib/cros_rust_registry/registry/system_api-*/src/bindings/client/

Dentro do comando de implementação de um D-Bus de conexão precisa ser inicializado. Uma conexão de bloqueio é usada neste exemplo.

let connection = Connection::new_system().map_err(|err| { error!("ERROR: Failed to get D-Bus connection: {}", err); dispatcher::Error::CommandReturnedError})?;

O barramento de conexão pode ser usada para obter uma interface para o serviço desejado, que é debugd neste caso:

let conn_path = connection.with_proxy( "org.chromium.debugd", "/org/chromium/debugd", DEFAULT_DBUS_TIMEOUT,);

O resto da chamada do método usa o fato de que o importado traço system_api::client::OrgChromiumDebugd é implementado por conn_path então, as funções de membro que mapeiam para o D-Bus métodos podem ser chamados a partir de conn_path. Por exemplo:

conn_path .update_and_verify_fwon_usb_stop(handle) .map_err(|err| { println!("ERROR: Got unexpected result: {}", err); dispatcher::Error::CommandReturnedError })?;

isto cobre as bases. Se você olhar para o código fonte real para a base::verificy_ro, ele fornece um exemplo mais complicado com uma chamada de método start, um observador, e uma chamada de método stop.

ajuda de comandos

as cadeias de Ajuda predefinidas são povoadas usando o nome do comando, a cadeia de Utilização, a cadeia de descrição e quaisquer opções ou opções que sejam registadas através da API do expedidor.

alternativamente, uma chamada de ajuda pode ser definida ao registrar o comando para executar uma lógica personalizada, como invocar a opção de ajuda de um binário. Por exemplo:

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!(); }}

Desactualizando comandos

Se quiser substituir um comando crosh por algum outro UI (como um cromo:// page), e quiser desactualizar o comando graciosamente deixando para trás uma nota amigável se as pessoas tentarem usá-lo, aqui está o formulário.

# 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")

certifique-se que adiciona o comentário de TODO para que as pessoas saibam no futuro quando é correcto limpá-lo.

Testing

Iterative Development

You can run./crosh on your desktop system to get a sample shell. Você pode testar rapidamente interações básicas (como análise de argumentos) aqui, ou verificar a saída de Ajuda. Você não terá acesso aos Serviços CrOS com os quais muitos comandos Cros esperam conversar (via D-Bus), então esses comandos falharão.

Se quiser carregar módulos do modo dev, poderá usar ./crosh --dev. Só irá carregar módulos locais (./dev.d/), por isso, se o seu módulo viver noutro local, poderá copiá-lo aqui temporariamente.

da mesma forma, se quiser carregar módulos de dispositivos removíveis, poderá usar ./crosh --removable.

Unittests

Para executar os testes de unidade chamada cargo test --workspace no crosh pasta ou executar o emege-${BOARD} crosh && FEATURES=test emerge-${BOARD}

./run_tests.sh legado unittest corredor executa um monte de estilo básico e a solidez de cheques. Compare – o com qualquer alteração ao código da shell!

trabalho futuro

qualquer pessoa deve sentir-se livre para pegar estas ideias e tentar implementá-las :).

  • Mova todos os comandos restantes que estão implementados no lugar para depurar as chamadas para que possam ser feitas por D-Bus.
  • execute o crosh numa caixa de areia restrita (namespaces/seccomp/etc…). Uma vez que todos os comandos são feitos através de IPC, não há necessidade de manter privs. Pode torná-lo dependente do modo dev embora para que não quebremos shell.
  • migre comandos legados adicionais para Rust. Isto também pode ser feito ao mesmo tempo em que migra um comando para o debugd.

Legacy Crosh Documentation

Crosh was originally written in shell. No momento da escrita, muitos dos comandos ainda estão no shell e ainda têm que ser portados para o Rust crosh. Esta documentação é mantida aqui para a manutenção destes comandos.

API de comando

para cada comando, você define duas variáveis e uma função. Não há necessidade de registrar os novos comandos em qualquer lugar como o crosh irá inspecionar o seu próprio ambiente de execução para descobri-los.

Aqui está como você registraria um novo comando .

# 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!...)

veja a secção de design abaixo para mais detalhes sobre o que e como estruturar o novo comando.

ajuda de comando

Se o seu comando crosh simplesmente chama para um programa externo para fazer o processamento, e esse programa já oferece detalhes de Utilização, você provavelmente não quer ter que duplicar as coisas. Você pode lidar com este cenário definindo uma função help_foo que faz a respectiva chamada.

# Set the help string so crosh can discover us automatically.HELP_foo=''cmd_foo() ( ...)help_foo() ( /some/command --help)

tome nota de que ainda definimosHELP_foo. Isto é necessário para que o crosh possa descobrir-nos automaticamente e mostrar-nos nas listas de utilizadores relevantes (como o comando help_advanced). Nós não precisamos definir embora desde a função help_foo faz isso para nós.

Ocultando Comandos

Se um comando ainda não está pronto para o “horário nobre”, você pode querer tê-lo em crosh para os testes iniciais, mas não mostrá-la no help saída onde os usuários podem facilmente descobrir o que (é claro que o código é pública, portanto, qualquer pessoa que ler a fonte real pode encontrá-lo). É assim que se faz.

# 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() ( ...)

Related Posts

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *