Complicado?
Variáveis de lado por um momento. Este é o seu código básico:
split --bytes 10M --numeric-suffixes --filter='cat | ssh root@$remote_ip "gzip >> /root/myfilecopy.gz"' /dev/myblockdev
Primeiro de tudo: cat
é inútil aqui .
Em seguida, acho que acrescentar os resultados de gzip
-s consecutivos ao mesmo arquivo ( >>
) cancela o trabalho de split
. Em teoria, no final, o que você ganha é apenas gzipped /dev/myblockdev
, exatamente como você fez:
ssh root@$remote_ip 'gzip > /root/myfilecopy.gz' < /dev/myblockdev
Na prática, eu pensaria em condição de corrida. Espero que split
execute ssh
-s em sequência no lado local; mas eu não ficaria surpreso se, em algumas circunstâncias, vários buffers ou atrasos no lado remoto fizessem com que o próximo gzip
começasse a escrever antes que o anterior terminasse. Isso corromperia myfilecopy.gz
. Abrir o arquivo apenas uma vez evita isso.
Se você usou $FILE
(consulte man 1 split
) e gravou em vários arquivos, eu veria o ponto de usar split
. Note que isso não introduziria uma condição de corrida porque cada um desses arquivos seria aberto apenas uma vez.
Conclusão: split
é provavelmente inútil, cat
é inútil, com certeza; o acréscimo descuidado pode corromper o arquivo resultante.
O problema que você perguntou sobre
OK, vamos supor que você tenha suas razões para usar split
e >>
desta maneira (seu cat
ainda é inútil).
Seu shell atual sabe o valor de $remote_file
, mas split
e seu (s) filtro (s) são processos filhos e eles não herdarão a variável, a menos que você export
antes. Variável inexistente se expande para nada, então o fragmento relevante se parece com gzip >> (newline)
, daí o erro.
O mesmo se aplica a $remote_ip
. Eu acho que no seu código você não usa $remote_ip
, mas o endereço IP real 192.168.0.105
. De agora em diante, eu uso remote_ip
como um espaço reservado (isto é, não uma variável shell) para o endereço IP real.
Para export
:
remote_file="/root/myfilecopy.gz"
export remote_file
# now your split command should utilize the variable as you expected
Como alternativa, você pode fazer com que seu shell atual expanda $remote_file
no momento em que você executar split
. Originalmente, a string $remote_file
é deixada intacta devido às aspas simples em torno dela. A sintaxe a seguir altera o tipo de aspas apenas para essa variável:
split --bytes 10M --numeric-suffixes --filter='ssh root@remote_ip "gzip >> '"$remote_file"'"' /dev/myblockdev
# close a single quote ^ ^ and open again
# variable inside double quotes ^^^^^^^^^^^^^^
Dessa forma, split
nunca recebe o literal $remote_file
, ele obtém seu valor.
Outra questão
Se você tivesse remote_file="/root/myfile copy.gz"
, o espaço no caminho dividiria em dois argumentos no lado remoto. Por essa razão, a abordagem mais robusta requer cotação adicional. Essa é a abordagem "sem exportação" acima com aspas extras (com escape de \
):
split --bytes 10M --numeric-suffixes --filter='ssh root@remote_ip "gzip >> \"'"$remote_file"'\""' /dev/myblockdev
Vamos tira-lo passo a passo. Entre outros argumentos, split
veria o seguinte como um único:
--filter=ssh root@remote_ip "gzip >> \"/root/myfile copy.gz\""
Ele executaria esse filtro em bash
:
ssh root@remote_ip "gzip >> \"/root/myfile copy.gz\""
Então ssh
veria isso como um de seus argumentos:
gzip >> "/root/myfile copy.gz"
Portanto, no lado remoto, o redirecionamento seria para "/root/myfile copy.gz"
. Sem essas citações adicionadas, você teria:
gzip >> /root/myfile copy.gz
que é equivalente a
gzip copy.gz >> /root/myfile
Notas adicionais
- Se a CPU local for rápida o suficiente, considere
gzip
antes dessh
. Dessa forma, você envia menos dados pelos links da rede; especialmente se você preparou seu dispositivo de bloco para compactar bem . - Se sua intenção era executar vários processos de
gzip
para obter vantagem de vários núcleos de CPU, observe que eles provavelmente seriam executados em sequência; se não, uma condição de corrida - você não quer isso. Familiarize-se compigz
.