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
gzipantes 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
gzippara 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.