Estou no Mac OS Big Sur e executando uma instância virtual do Linux Ubuntu 16.04 (usando vagrant). Eu posso executar os dois comandos a seguir (um para ssh no servidor virtual e o segundo para executar um comando dentro dele)…
$ ssh myvirtual.local
Warning: Permanently added '10.0.4.19' (ECDSA) to the list of known hosts.
Last login: Wed Sep 15 16:37:57 2021 from 10.0.4.1
$ foreman start -f Procfile.debug
16:38:26 rails.1 | started with pid 27884
16:38:26 worker.1 | started with pid 27885
16:38:26 scheduler.1 | started with pid 27887
...
Eu gostaria de poder combinar esses dois comandos, então tentei
$ ssh -t myvirtual.local 'foreman start -f Procfile.debug’
Warning: Permanently added '10.0.4.19' (ECDSA) to the list of known hosts.
bash: foreman: command not found
Connection to 10.0.4.19 closed.
Estou confuso sobre qual outra configuração eu precisaria executar para ter um único comando para simular o que estou fazendo inicialmente. Alguma ideia?
A principal diferença neste caso é que
ssh host
inicia o seu shell de login no modo de login (sshd
inicia-o com-
prefixo ao seuargv[0]
que diz ao shell que ele deve inicializar a sessão de login lendo um script de inicialização.profile
,.bash_profile
,.zprofile
,.zlogin
ou.login
(e possivelmente os do sistema em/etc
) dependendo na implementação do shell) e interativamente (na medida em que emite prompts para obter entrada de você). Esse é orlogin
modo dessh
.Enquanto estiver em
ssh -t host 'some shell code'
,sshd
executa seu shell de login com-c
esome shell code
como argumento, mas sem dizer que é um shell de login. Esse shell também não é interativo, o código não é solicitado a partir de um terminal. Esse é orsh
modo.E provavelmente no seu caso, o comando não pode ser encontrado porque algumas diretivas nos arquivos de inicialização de sessão para definir a
$PATH
variável não foram executadas.Observe que nem todos os shells podem ser um shell de login e interpretar o código fornecido como argumento.
A
bash
casca pode embora.bash
iniciará como um shell de login quando forargv[0]
iniciado com ,-
mas também quando passar uma opção-l
ou--login
, e então1¹ ainda lerá os arquivos de inicialização da sessão de login mesmo se passar um comando para executar-c
(exceto no modo POSIX).Então aqui, em vez de fazer:
Você poderia fazer:
Que iniciará outro
bash
, mas desta vez como um shell de login (que interpretará o código~/.bash_profile
e possivelmente algum em/etc/profile
ou/etc/profile.d
onde$PATH
está a inicialização) antes de interpretar osome code
.Ou você pode tentar localizar o arquivo onde a
$PATH
definição é feita e fazer:Isso ainda deixa outra diferença, pois esse shell não é interativo e seus arquivos de inicialização podem decidir se comportar de maneira diferente quando interativos de quando não são (verificando a presença de
i
in$-
ou verificando a presença de uma$PS1
variável).bash
não interpreta~/.bashrc
(o arquivo de personalização do shell interativo) na inicialização quando executado como um shell de login, mesmo quando interativo (ao contrário do que acontece na maioria dos outros shells), mas a maioria das pessoas contorna essa decisão de design bizarra adicionando umsource ~/.bashrc
em seus arquivos~/.bash_profile
. O padrão~/.profile
no Debian e derivados faz isso por padrão (somente quando o shell ébash
claro).bash
não interpreta~/.bashrc
quando invocado por ssh por padrão, mas pode ser configurado em tempo de compilação para fazê-lo usando aSSH_SOURCE_BASHRC
opção de configuração. Debian e derivados como o Ubuntu permitem isso. Portanto, ao fazerssh ubuntu-host 'some code'
, e se seu shell de login for bash nessa máquina, obash
shell quesshd
iniciará interpretará~/.bashrc
antes de interpretarsome code
.O
~/.bashrc
mesmo acaba sendo interpretado no modorlogin
ersh
, mas, conforme observado por @Quasimodo, o padrão~/.bashrc
no Debian e no Ubuntu tem isso no topo:Portanto, se houver uma
$PATH
definição abaixo dessas linhas, elas serão interpretadas apenas norlogin
modo (ondebash
é interativo,$-
contémi
e~/.bashrc
é originado por~/.profile
), e não norsh
modo (onde~/.bashrc
é originado, mas a maior parte de seu conteúdo é ignorada como o shell não é interativo).¹ no caso de
argv[0]
iniciar com-
(ao invés de com-l
/--login
), se ele será tratado como shell de login ou não quando passado a-c code
depende sebash
foi compilado comNON_INTERACTIVE_LOGIN_SHELLS
habilitado ou não.Você está perdendo as configurações de ambiente, pois esses dois cenários nem sempre são equivalentes:
Este próximo bloco de comando lhe dará o conjunto de variáveis que estão faltando em sua solução preferida (o segundo formato nos dois exemplos acima). Você pode adicioná-los à sua pergunta e eu vou completar esta para explicar como defini-los, ou você mesmo pode usar as informações para defini-los.
Saída de exemplo abreviada de um sistema que tenho aqui
Isso não tem nada específico para Ruby ou Rails, mas mostra que no meu caso a
PATH
variável é diferente (você poderia ver os valores reais em/tmp/env.1
and/tmp/env.2
).Depois de rastreá-lo e classificá-lo, você pode querer executar
foreman
emscreen
outmux
, para que ele não receba umSIGHUP
sinal quando assh
conexão for encerrada. Mas eu recomendo que você comece resolvendo o problema inicial antes de introduzir qualquer uma dessas ferramentas adicionais.