Como proteger a cópia 5 dos arquivos mais recentes no diretório local

1

Eu tenho essa linha única de código

scp -r ${server}:${server_dir}/$(ssh ${server} "ls -t ${server_dir} | head -5") logs/ios

que quando executado, scp apenas o mais recente dos cinco arquivos, com a seguinte saída

iosTestOutput_20180831-175508-PDT.tgz                                                                100%  199KB  21.7MB/s   00:00
cp: iosTestOutput_20180831-155546-PDT.tgz: No such file or directory
cp: iosTestOutput_20180831-142509-PDT.tgz: No such file or directory
cp: iosTestOutput_20180831-124259-PDT.tgz: No such file or directory
cp: iosTestOutput_20180831-115001-PDT.tgz: No such file or directory

No entanto, eu tenho ssh-ed no diretório de destino e observei que esses arquivos existem, então não tenho certeza do que estou fazendo de errado.

    
por the_prole 04.09.2018 / 19:11

3 respostas

2

Apenas o primeiro arquivo tem o caminho absoluto que o scp precisa.

${server}:${server_dir}/$(ssh ${server} "ls -t ${server_dir} | head -5") será avaliado como

${server}:${server_dir}/iosTestOutput_20180831-175508-PDT.tgz
iosTestOutput_20180831-155546-PDT.tgz
iosTestOutput_20180831-142509-PDT.tgz
...

Eu usei retornos de linha em vez de espaços para maior clareza.

Essencialmente, você precisa ter um loop sobre uma lista gerada usando algo que produza o caminho completo para cada um dos cinco arquivos. O link pode ser um bom começo.

(não testado, apenas um esboço) Algo como:

for bkp in $(ssh ${server} "find ${absolute_path_remote_dir} -type f -exec stat -c '%X %n' {} \; | sort -nr | awk 'NR==1,NR==5 {print $2}'")
do
scp -r ${bkp} logs/ios
done

Também pode haver alguma opção no rsync que o ajudará a realizar o que você está procurando de maneira mais elegante.

    
por 04.09.2018 / 19:46
0

Quando você executou:

scp -r ${server}:${server_dir}/$(ssh ${server} "ls -t ${server_dir} | head -5")

... a primeira coisa (importante) que aconteceu foi que o seu shell local começou a interpretar a substituição do comando aqui:

$(ssh ${server} "ls -t ${server_dir} | head -5")

A substituição do comando acima faz basicamente o que você pensa, exceto que ele quebra assim que há um espaço ou uma nova linha (ou tab) em um nome de arquivo. Você pode, por exemplo, ter esses 5 arquivos mais recentes:

  • temp file
  • a
  • b
  • c
  • d

O ssh ... ls -t | head -5 fornecerá:

a
b
c
d
temp file

... mas a substituição de comandos retira novas linhas da saída, deixando-o com esta cadeia a ser devolvida:

a b c d temp file

... que agora é indistinguível dos nomes de arquivo reais e originais.

Você pode nunca encontrar esse nome de arquivo, mas é mais seguro assumir a segurança e nunca ser mordido do que o contrário.

Como resultado, sugiro uma direção na qual você recupere os nomes de arquivos com segurança para o sistema local e, em seguida, recupere-os especificamente:

server=server-name-here  ## replace with your values
server_dir=/tmp          ## replace with your values

files=($(ssh "$server" "zsh -c 'print -N -- ${server_dir}/*(om.[1,5])'" 2>/dev/null ) )
for f in ${files[1,5]}
do
  scp "${server}:${f}" logs/ios
done

A parte mais difícil é recuperar a lista remota dos cinco arquivos mais recentemente modificados. Aqui, eu estou ssh'ing para o servidor e invocando zsh para usar seu mecanismo de globbing extensa para retornar:

  • arquivos do diretório $ {server_dir}
  • que são o sob rered m tempo de odificação
  • e são arquivos regulares ( . )
  • e apenas os cinco primeiros: [1,5]

O comando zsh built-in print é usado aqui para retornar uma lista separada por nulo - e terminada em nulo - dos arquivos resultantes. Essa cadeia contendo nulo é passada de volta por meio de ssh para zsh, que divide a cadeia em nulos e atribui o conteúdo à matriz files .

Em seguida, percorremos essa matriz, tomando cuidado para pegar apenas os primeiros cinco elementos (como o sexto é um valor nulo), em seguida, chamamos scp em cada um desses arquivos.

Se você quisesse, poderia criar cuidadosamente uma cadeia de nomes de arquivos remotos ( ${server}:${file1} ${server}:${file2} ... ) e chamar scp apenas uma vez. Uma possibilidade poderia ser:

scp ${server}:${(qq)^files[1,5]} logs/ios

... conforme instrui o zsh a preceder a string ($ {server}, que é substituída pelo seu nome real do servidor, seguido por dois pontos) aos cinco primeiros elementos da matriz. Qualquer nome de arquivo da matriz é citado.

    
por 04.09.2018 / 20:38
-1

Como hhoke1 disse que você está perdendo o caminho absoluto.

ls -t | head -5 | xargs readlink -f

Isso deve dar a você um caminho absoluto para scp, mas parece que readlink não pode ler a entrada do pipe, então usei xargs .

    
por 05.09.2018 / 02:06

Tags