Como mover / renomear um arquivo usando uma tarefa Ansible em um sistema remoto
202
Como é possível mover / renomear um arquivo / diretório usando um módulo Ansible em um sistema remoto? Não quero usar as tarefas de comando / shell e não quero copiar o arquivo do sistema local para o sistema remoto.
Só queria saber se existe uma maneira sem usar as tarefas mencionadas. Parece que não há outra maneira no momento.
Christian Berendt
1
Por que você deseja movê-lo especificamente em vez de copiá-lo? Parece uma ação pontual, em vez de uma etapa idempotente de garantir o estado do sistema.
Nick Urban.
2
Eu tenho um arquivo de configuração de amostra incluído em um pacote RPM e desejo mover esse arquivo de configuração de exemplo.
Christian Berendt
1
No momento, estou usando um link simbólico para fazer referência ao arquivo. Usar get_url não é uma opção para mim, porque o sistema não pode acessar a Internet.
Christian Berendt
Respostas:
201
O módulo de arquivo não copia arquivos no sistema remoto. O parâmetro src é usado apenas pelo módulo de arquivo ao criar um link simbólico para um arquivo.
Se você deseja mover / renomear um arquivo inteiramente em um sistema remoto, sua melhor aposta é usar o módulo de comando para chamar o comando apropriado:
- name: Move foo to bar
command: mv /path/to/foo /path/to/bar
Se você quiser ser extravagante, poderá primeiro usar o módulo stat para verificar se o foo realmente existe:
- name: stat foo
stat: path=/path/to/foo
register: foo_stat
- name: Move foo to bar
command: mv /path/to/foo /path/to/bar
when: foo_stat.stat.exists
Sem usar o módulo de comando, sua única outra opção seria escrever seu próprio módulo personalizado.
Bruce P
2
Marcado como resposta correta, porque esta é a maneira atual de copiar arquivos remotos.
Christian Berendt
11
Em relação à observação antes de saltar: existe algum motivo para não usar a removesopção do commandmódulo (documentada aqui )? Parece que essa opção faria o Ansible checar primeiro.
21715 Jim Jimitsitsy
2
O Ansible rastreia as alterações para notificar o manipulador, o que torna essa solução abaixo do ideal.
boh
3
Você não precisa verificar manualmente a existência do arquivo se usar removes: /path/to/fooe creates: /path/to/bar. A @Fonant já mencionou isso como comentário em outra resposta, mas como essa é a aceita, quero apontar novamente.
Michael Trojanek
218
A partir da versão 2.0 , no módulo de cópia, você pode usar o remote_srcparâmetro
Se Truefor para a máquina remota / de destino do src.
- name: Copy files from foo to bar
copy: remote_src=True src=/path/to/foo dest=/path/to/bar
Se você deseja mover o arquivo, é necessário excluir o arquivo antigo com o módulo de arquivo
- name: Remove old files foo
file: path=/path/to/foo state=absent
A partir da versão 2.8, o módulo de cópiaremote_src suporta cópia recursiva.
Pequena observação: "Atualmente o remote_src não suporta cópia recursiva." extraído do módulo ansible doc. Portanto, se você deseja copiar recursivamente, ainda precisa do módulo shell / comando.
Klaas
23
Eu não entendo Copiar e excluir não é o mesmo que mover. Por um lado, não é atômico. Por outro, é mais lento, especialmente para arquivos grandes. Sou novo no Ansible, mas isso me parece muito estranho.
mlissner
19
@ alex o que estou dizendo é que não pode ser o caminho certo para fazer isso. Eu estou indo contra o vento contra 50 votos positivos, mas isso é loucura. Outro problema: permissões e outros atributos não são mantidos. Outro: E se o arquivo for alterado durante a cópia ?
mlissner
2
@Hamish Downer e mlissner. Eu não disse que é a melhor solução para todas as suas necessidades. Também escrevi que, se você deseja copiar muitos arquivos, não deve usar o módulo de cópia. Leia a pergunta "Não quero usar as tarefas de comando / shell".
Alex
7
@ Alex, esta é a segunda resposta mais votada em uma pergunta sobre a movimentação de arquivos com idempotência. A questão não é sobre cópia. Existem muitos problemas com a cópia em vez de mover, portanto, esta resposta está incorreta. Por isso, recebe um voto negativo. A etiqueta no SO é explicar votos negativos. Como observado em outro lugar, a melhor opção até agora é:command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Alec Wenzowski 29/11
106
Eu encontrei a opção de criação no módulo de comando útil. Que tal agora:
- name: Move foo to bar
command: creates="path/to/bar" mv /path/to/foo /path/to/bar
Eu costumava fazer uma abordagem de duas tarefas usando estatísticas, como sugere Bruce P. Agora eu faço isso como uma tarefa com cria. Eu acho que isso é muito mais claro.
Isso não funciona localmente em todos os casos, porque desté acessado através do SSH, mesmo que o diretório esteja na mesma máquina.
Karl Richter
5
Outra maneira de conseguir isso é usando filecom state: hard.
Este é um exemplo que eu tenho que trabalhar:
- name: Link source file to another destination
file:
src: /path/to/source/file
path: /target/path/of/file
state: hard
Apenas testado no localhost (OSX), mas deve funcionar também no Linux. Eu não posso dizer para o Windows.
Observe que caminhos absolutos são necessários. Senão, não me deixaria criar o link. Além disso, você não pode atravessar sistemas de arquivos; portanto, o trabalho com qualquer mídia montada pode falhar.
O hardlink é muito semelhante ao movimento, se você remover o arquivo de origem depois:
- name: Remove old file
file:
path: /path/to/source/file
state: absent
Outro benefício é que as mudanças persistem quando você está no meio de uma peça. Portanto, se alguém alterar a fonte, qualquer alteração será refletida no arquivo de destino.
Você pode verificar o número de links para um arquivo via ls -l. O número de links físicos é mostrado próximo ao modo (por exemplo, rwxr-xr-x 2, quando um arquivo possui 2 links).
Infelizmente, isso não vai funcionar para um diretório, como hard links não são permitidos para os diretórios (((
de Drew
1
Esta resposta faz uma suposição sobre o sistema de destino, especificamente que src e dest estão na mesma partição. Isso pode não ser verdade e, portanto, esta resposta não deve ser usada.
Mikky 24/04/19
4
Bruce não estava tentando determinar o destino para verificar se movia ou não o arquivo, se ele já estava lá; ele estava se certificando de que o arquivo a ser movido realmente existia antes de tentar o mv.
Se o seu interesse, como o de Tom, é apenas mudar se o arquivo ainda não existir, acho que ainda devemos integrar o cheque de Bruce na mistura:
- name: stat foo
stat: path=/path/to/foo
register: foo_stat
- name: Move foo to bar
command: creates="path/to/bar" mv /path/to/foo /path/to/bar
when: foo_stat.stat.exists
Não há necessidade de usar when: stat_result.stat.exists == True. Apenas usar when: stat_result.stat.existsé bom o suficiente.
Kurtumiah #
Eu normalmente uso o == Trueporque estou sempre fazendo algo quando o arquivo não é encontrado ou == False.
Eduprado 6/08/19
De acordo com a página da documentação oficial dastatexists propriedade do módulo , retorna um booleanvalor. Portanto, se você colocar apenas when: stat_result.stat.existsisso, satisfará a condição se o arquivo estiver presente, o que também é idêntico, when: stat_result.stat.exists == Truemas com mais textos e verificação condicional desnecessária.
precisa saber é
0
Isso pode parecer um exagero, mas se você quiser evitar o uso do módulo de comando (o que eu faço, porque ele não é idempotente), você pode usar uma combinação de copiar e desarquivar.
Use tar para arquivar os arquivos necessários. Se você pensa no futuro, isso realmente faz sentido. Você pode querer uma série de arquivos em um determinado diretório. Crie esse diretório com todos os arquivos e arquive-os em um tar.
Use o módulo desarquivar. Ao fazer isso, junto com o destino: e remote_src: keyword, você pode copiar todos os seus arquivos para uma pasta temporária para começar e depois descompactá-los exatamente onde quiser.
Sei que é um tópico antigo de ANOS , mas fiquei frustrado e criei uma função para fazer exatamente isso em uma lista arbitrária de arquivos. Estenda como achar melhor:
- name: stat the file
stat:
path: {{ item }}
register: my_file
- name: hard link the file into directory
file:
src: /original/path/to/{{ item }}
dest: /path/to/directory/{{ item }}
state: hard
when: my_file.stat.exists
- name: Delete the original file
file:
path: /original/path/to/{{ item }}
state: absent
when: my_file.stat.exists
Observe que a vinculação física é preferível à cópia aqui, pois preserva inerentemente a propriedade e as permissões (além de não consumir mais espaço em disco para uma segunda cópia do arquivo).
Respostas:
O módulo de arquivo não copia arquivos no sistema remoto. O parâmetro src é usado apenas pelo módulo de arquivo ao criar um link simbólico para um arquivo.
Se você deseja mover / renomear um arquivo inteiramente em um sistema remoto, sua melhor aposta é usar o módulo de comando para chamar o comando apropriado:
Se você quiser ser extravagante, poderá primeiro usar o módulo stat para verificar se o foo realmente existe:
fonte
removes
opção docommand
módulo (documentada aqui )? Parece que essa opção faria o Ansible checar primeiro.removes: /path/to/foo
ecreates: /path/to/bar
. A @Fonant já mencionou isso como comentário em outra resposta, mas como essa é a aceita, quero apontar novamente.A partir da versão 2.0 , no módulo de cópia, você pode usar o
remote_src
parâmetroSe
True
for para a máquina remota / de destino do src.Se você deseja mover o arquivo, é necessário excluir o arquivo antigo com o módulo de arquivo
A partir da versão 2.8, o módulo de cópia
remote_src
suporta cópia recursiva.fonte
command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Eu encontrei a opção de criação no módulo de comando útil. Que tal agora:
Eu costumava fazer uma abordagem de duas tarefas usando estatísticas, como sugere Bruce P. Agora eu faço isso como uma tarefa com cria. Eu acho que isso é muito mais claro.
fonte
command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Outra opção que funcionou bem para mim é usar o módulo de sincronização . Em seguida, remova o diretório original usando o módulo de arquivo.
Aqui está um exemplo dos documentos:
fonte
dest
é acessado através do SSH, mesmo que o diretório esteja na mesma máquina.Outra maneira de conseguir isso é usando
file
comstate: hard
.Este é um exemplo que eu tenho que trabalhar:
Apenas testado no localhost (OSX), mas deve funcionar também no Linux. Eu não posso dizer para o Windows.
Observe que caminhos absolutos são necessários. Senão, não me deixaria criar o link. Além disso, você não pode atravessar sistemas de arquivos; portanto, o trabalho com qualquer mídia montada pode falhar.
O hardlink é muito semelhante ao movimento, se você remover o arquivo de origem depois:
Outro benefício é que as mudanças persistem quando você está no meio de uma peça. Portanto, se alguém alterar a fonte, qualquer alteração será refletida no arquivo de destino.
Você pode verificar o número de links para um arquivo via
ls -l
. O número de links físicos é mostrado próximo ao modo (por exemplo, rwxr-xr-x 2, quando um arquivo possui 2 links).fonte
Bruce não estava tentando determinar o destino para verificar se movia ou não o arquivo, se ele já estava lá; ele estava se certificando de que o arquivo a ser movido realmente existia antes de tentar o mv.
Se o seu interesse, como o de Tom, é apenas mudar se o arquivo ainda não existir, acho que ainda devemos integrar o cheque de Bruce na mistura:
fonte
Foi assim que consegui trabalhar para mim:
o manual acima, verificará se o arquivo abc.xts existe antes de mover o arquivo para a pasta tmp.
fonte
when: stat_result.stat.exists == True
. Apenas usarwhen: stat_result.stat.exists
é bom o suficiente.== True
porque estou sempre fazendo algo quando o arquivo não é encontrado ou== False
.stat
exists
propriedade do módulo , retorna umboolean
valor. Portanto, se você colocar apenaswhen: stat_result.stat.exists
isso, satisfará a condição se o arquivo estiver presente, o que também é idêntico,when: stat_result.stat.exists == True
mas com mais textos e verificação condicional desnecessária.Isso pode parecer um exagero, mas se você quiser evitar o uso do módulo de comando (o que eu faço, porque ele não é idempotente), você pode usar uma combinação de copiar e desarquivar.
fonte
Você pode fazer isso por -
Usando o comando ad hoc
Ou você, se você quiser fazê-lo usando o playbook
fonte
Sei que é um tópico antigo de ANOS , mas fiquei frustrado e criei uma função para fazer exatamente isso em uma lista arbitrária de arquivos. Estenda como achar melhor:
main.yml
move.yml
Observe que a vinculação física é preferível à cópia aqui, pois preserva inerentemente a propriedade e as permissões (além de não consumir mais espaço em disco para uma segunda cópia do arquivo).
fonte
No Windows:
- name: Move old folder to backup win_command: "cmd.exe /c move /Y {{ sourcePath }} {{ destinationFolderPath }}"
Para renomear, use o comando rename ou ren
fonte