man su
diz:
You can use the -- argument to separate su options from the arguments
supplied to the shell.
man bash
diz:
-- A -- signals the end of options and disables further option
processing. Any arguments after the -- are treated as filenames
and arguments. An argument of - is equivalent to --.
Bem, então, vamos ver:
[root ~] su - yuri -c 'echo "$*"' -- 1 2 3
2 3
[root ~] su - yuri -c 'echo "$*"' -- -- 1 2 3
2 3
[root ~] su - yuri -c 'echo "$*"' -- - 1 2 3
1 2 3
[root ~] su - yuri -c 'echo "$*"' - 1 2 3
1 2 3
O que eu esperava (a saída do segundo comando difere):
[root ~] su - yuri -c 'echo "$*"' -- 1 2 3
2 3
[root ~] su - yuri -c 'echo "$*"' -- -- 1 2 3
1 2 3
[root ~] su - yuri -c 'echo "$*"' -- - 1 2 3
1 2 3
[root ~] su - yuri -c 'echo "$*"' - 1 2 3
1 2 3
Provavelmente não é um grande problema. Mas o que está acontecendo lá? A segunda e a terceira variantes parecem o caminho a seguir, mas uma delas não funciona. O quarto parece não confiável, -
pode ser tratado como su
opção.
bash 4.2.45
as contas de origem e de destino.Respostas:
O que está acontecendo é que o primeiro argumento que você fornece ao shell é o
$0
parâmetro (normalmente esse seria o nome do shell). Não está incluído quando você faz,echo $*
pois$*
todos os argumentos são separados$0
.Exemplo:
Atualizar
Executando o seguinte comando:
produz a linha de strace:
Então, de alguma forma, parece que, neste caso,
su
está devorando o extra--
sem passar para o bash, possivelmente devido a um bug (ou pelo menos comportamento não documentado). No entanto, não vai consumir mais do que dois dos--
argumentos:fonte
su - yuri -c 'echo "$*"' -- -- 1 2 3
:, o shell supostamente recebe-- 1 2 3
, mas apenas produz2 3
. Isso faz algum sentido?bash -c 'echo $*' -- 1 2 3
, sai1 2 3
como esperado.su
bug.Na verdade, a resposta de @ Graeme - e sua pergunta - estão apenas referenciando os efeitos colaterais de como o shell lida.
"$@positional $*parameters".
Estes são atribuídos pelo shell aos seus argumentos na chamada e a qualquer momento depois com oset
utilitário interno. Eles podem ser chamados a qualquer momento, com o"$*"
qual divide cada posição com o primeiro caractere"$IFS"
ou"$@"
que cita cada posição e os divide com todos os"$IFS."
Se você já possui os valores que está alimentando com a concha, não precisa
--
três vezes. Os parâmetros do shell sãoset
capazes - sempre, a qualquer momento, não apenas na chamada (exceto $ 0 e -i):E todas essas citações de shell podem ser confusas. Isso simplifica um pouco as coisas:
Os argumentos do shell pai são
set
4, 5 e 6 e depois são passados para o subshell invocado porsu
meio da posiçãoparameter "$@array".
Observe como eu
( subshell )
o comando acima - faço isso porque não quero mexer no meu ambiente de shell atual - porque posso inadvertidamente alterar algo que preferiria não fazer se fizesse comset.
SOBRE REDIRECÇÃO:
Primeiro de tudo, seu sistema Unix funciona com arquivos - permissões de arquivos, conteúdo e atributos de arquivos. De uma maneira ou de outra, todos os objetos de dados que você usa podem (e, pelo menos na minha opinião, deveriam) ser endereçados como um arquivo. O redirecionamento aponta para um arquivo - é tudo. A
<<HERE-DOCUMENT
descreverá um arquivo em linha e o redirecionará. As expansões de shell são interpretadas ou não.O autor da pergunta observa nos comentários abaixo que, quando ele tenta usar esse método como
root
usuário, ele recebe um erro de permissão. Quando respondi, sugeri que elechown
ouchgrp
o/dev/fd/${num}
arquivo especial, mas esse provavelmente não é o melhor método. A razão pela qual ele encontra esse problemaroot
é concederread
permissões, mas nãoexecute
permissões. Você pode lidar com isso facilmente, apenas evitando umaexec
chamada. Em vez de chamar o/dev/fd/${num}
arquivo diretamente na linha de comando, faça:O uso de dois heredocs pode ajudar a escapar. Aqui está o que acontece em todos os casos:
NO SET IN
<<HEREDOC
RESULTADO
SET
"$@"
IN<<HEREDOC
RESULTADO
SET
"$@"
E MAIS EM<<HEREDOC
RESULTADO
fonte
"8 9\n4 5 6\n"
. Estou correndodebian 6
,bash-4.1.5
esu
.root
ele diz:-su: /dev/fd/4: Permission denied
. Você sabe o que isso significa, a propósito? Caso contrário, ele será exibido como você diz, mas não aborda a questão. A pergunta é sobre o uso de--
e-
.chown /dev/fd/4
pela duração que precisar, ou apenaschgrp
. Não tenho muito tempo para testar agora. Mas isso é um pouco irrelevante, como foi o outro, você não precisa passar argumentos no final - basta trabalhar sua citação. Veja Agora?su
não podermos trabalhar com redirecionadosstdin
, passar argumentos ainda é melhor do que injetá-los no comando. Porque no último caso, você precisa escapar deles.