วิธีย้าย / เปลี่ยนชื่อไฟล์โดยใช้งาน Ansible บนระบบรีโมต


202

เป็นไปได้อย่างไรที่จะย้าย / เปลี่ยนชื่อไฟล์ / ไดเรกทอรีโดยใช้โมดูล Ansible บนระบบระยะไกล? ฉันไม่ต้องการใช้งานคำสั่ง / เชลล์และฉันไม่ต้องการคัดลอกไฟล์จากระบบโลคัลไปยังระบบรีโมต


ทำไมคุณไม่ต้องการใช้คำสั่ง / เปลือก?
Nick Urban

4
แค่อยากรู้ว่ามีวิธีใดบ้างโดยไม่ใช้งานที่กล่าวมา ดูเหมือนว่าไม่มีวิธีอื่นในขณะนี้
Christian Berendt

1
ทำไมคุณต้องการย้ายเฉพาะแทนการคัดลอก ดูเหมือนว่าเป็นการกระทำแบบครั้งเดียวแทนที่จะเป็นขั้นตอนที่ทำให้มั่นใจได้ว่า idempotent ช่วยให้มั่นใจได้ว่าเป็นขั้นตอนของระบบ
Nick Urban

2
ฉันมีไฟล์การกำหนดค่าตัวอย่างรวมอยู่ในแพ็คเกจ RPM และฉันต้องการย้ายไฟล์การกำหนดค่าตัวอย่างนี้
Christian Berendt

1
ในขณะนี้ฉันใช้ symlink เพื่ออ้างอิงไฟล์ การใช้ get_url ไม่มีทางเลือกให้ฉันเพราะระบบไม่สามารถเข้าถึงอินเทอร์เน็ต
Christian Berendt

คำตอบ:


201

โมดูลไฟล์ไม่ได้คัดลอกไฟล์ในระบบระยะไกล พารามิเตอร์ src ถูกใช้โดยโมดูลไฟล์เมื่อสร้าง symlink ไปยังไฟล์เท่านั้น

หากคุณต้องการย้าย / เปลี่ยนชื่อไฟล์ทั้งหมดในระบบรีโมตทางออกที่ดีที่สุดคือการใช้โมดูลคำสั่งเพื่อเรียกใช้คำสั่งที่เหมาะสม:

- name: Move foo to bar
  command: mv /path/to/foo /path/to/bar

หากคุณต้องการจินตนาการก่อนอื่นคุณสามารถใช้โมดูล stat เพื่อตรวจสอบว่า foo มีอยู่จริง:

- 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

3
โดยไม่ต้องใช้โมดูลคำสั่งเกี่ยวกับทางเลือกอื่นของคุณคือเขียนโมดูลที่คุณกำหนดเอง
บรูซ P

2
แท็กเป็นคำตอบที่ถูกต้องเพราะนี่เป็นวิธีปัจจุบันในการคัดลอกไฟล์ระยะไกล
Christian Berendt

11
เกี่ยวกับการมองก่อนที่คุณจะกระโดด: มีเหตุผลที่จะไม่ใช้removesตัวเลือกในcommandโมดูล (เอกสารที่นี่ )? ดูเหมือนว่าตัวเลือกนั้นจะทำการตรวจสอบ Ansible ก่อน
Jim Witschey

2
Ansible ติดตามการเปลี่ยนแปลงเพื่อแจ้งการจัดการซึ่งทำให้การแก้ปัญหานี้ไม่ดี
boh

3
คุณไม่จำเป็นต้องตรวจสอบด้วยตนเองสำหรับการดำรงอยู่ของไฟล์ถ้าคุณใช้และremoves: /path/to/foo creates: /path/to/bar@Fonant พูดถึงสิ่งนี้เป็นความคิดเห็นในคำตอบอื่นแล้ว แต่เนื่องจากนี่เป็นคำตอบที่ยอมรับได้ฉันต้องการชี้ให้เห็นอีกครั้ง
Michael Trojanek

218

จากเวอร์ชัน 2.0ในโมดูลคัดลอกคุณสามารถใช้remote_srcพารามิเตอร์

ถ้าTrueมันจะไปที่เครื่องรีโมต / เป้าหมายสำหรับ src

- name: Copy files from foo to bar
  copy: remote_src=True src=/path/to/foo dest=/path/to/bar

หากคุณต้องการย้ายไฟล์คุณต้องลบไฟล์เก่าด้วยโมดูลไฟล์

- name: Remove old files foo
  file: path=/path/to/foo state=absent

จาก โมดูลการคัดลอก เวอร์ชัน 2.8remote_srcรองรับการคัดลอกซ้ำ


29
ข้อสังเกตเล็กน้อย: "ปัจจุบัน remote_src ไม่รองรับการคัดลอกซ้ำ" นำมาจากเอกสารโมดูล ansible ดังนั้นหากคุณต้องการคัดลอกซ้ำคุณยังคงต้องการโมดูลเชลล์ / คำสั่ง
klaas

23
ฉันไม่เข้าใจ การคัดลอกจากนั้นการลบจะไม่เหมือนกับการย้าย สำหรับหนึ่งมันไม่ใช่อะตอม ส่วนอีกไฟล์จะช้ากว่าโดยเฉพาะไฟล์ขนาดใหญ่ ฉันใหม่กับ Ansible แต่ดูเหมือนว่าแปลกสำหรับฉัน
mlissner

19
@alex สิ่งที่ฉันพูดไม่สามารถเป็นวิธีที่ถูกต้องในการทำเช่นนี้ ฉันจะทวนลมเทียบกับ 50 upvotes แต่นี่มันบ้าไปแล้ว ปัญหาอื่น: สิทธิ์และคุณลักษณะอื่น ๆ ไม่ได้รับการปรับปรุง อื่น: เกิดอะไรขึ้นถ้าไฟล์มีการเปลี่ยนแปลงระหว่างการคัดลอก ?
mlissner

2
@Hamish Downer และ mlissner ฉันไม่ได้บอกว่ามันเป็นทางออกที่ดีที่สุดสำหรับทุกความต้องการของคุณ นอกจากนี้ฉันเขียนว่าหากคุณต้องการคัดลอกไฟล์จำนวนมากคุณไม่ควรใช้โมดูลคัดลอก อ่านคำถาม "ฉันไม่ต้องการใช้งานคำสั่ง / เชลล์"
อเล็กซ์

7
@Alex นี่คือคำตอบที่ได้รับการโหวตสูงสุดเป็นอันดับสองสำหรับคำถามเกี่ยวกับการย้ายไฟล์แบบไม่ใช้ความเร็ว คำถามไม่ได้เกี่ยวกับการคัดลอก มีปัญหามากมายเกี่ยวกับการคัดลอกแทนการย้ายดังนั้นคำตอบนี้ไม่ถูกต้อง ดังนั้นมันจึงได้รับการโหวต มารยาทบน SO คือการอธิบาย downvotes ตัวเลือกที่ดีที่สุดคือcommand: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Alec Wenzowski

106

ฉันได้พบตัวเลือกการสร้างในโมดูลคำสั่งที่มีประโยชน์ เกี่ยวกับสิ่งนี้:

- name: Move foo to bar
  command: creates="path/to/bar" mv /path/to/foo /path/to/bar

ฉันเคยทำ 2 วิธีการทำงานโดยใช้สถิติเช่น Bruce P แนะนำ ตอนนี้ฉันทำสิ่งนี้เป็นงานเดียวกับสร้าง ฉันคิดว่านี่ชัดเจนกว่ามาก


60
หรือดียิ่งขึ้น: command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Fonant

8

ตัวเลือกที่มีการทำงานได้ดีสำหรับฉันก็คือการใช้โมดูลประสาน จากนั้นลบไดเรกทอรีเดิมโดยใช้โมดูลไฟล์

นี่คือตัวอย่างจากเอกสาร:

- synchronize:
    src: /first/absolute/path
    dest: /second/absolute/path
    archive: yes
  delegate_to: "{{ inventory_hostname }}"

สิ่งนี้ไม่สามารถใช้งานได้ในทุกกรณีเพราะdestเข้าถึงผ่าน SSH แม้ว่าไดเรกทอรีจะอยู่ในเครื่องเดียวกัน
Karl Richter

5

วิธีการที่จะบรรลุเป้าหมายนี้ก็คือการใช้กับfilestate: hard

นี่คือตัวอย่างที่ฉันต้องทำงาน:

- name: Link source file to another destination
  file:
    src: /path/to/source/file
    path: /target/path/of/file
    state: hard

ทดสอบบน localhost (OSX) เท่านั้น แต่ควรใช้กับ Linux ด้วย ฉันบอก Windows ไม่ได้

โปรดทราบว่าจำเป็นต้องใช้พา ธ สัมบูรณ์ อย่างอื่นมันจะไม่ให้ฉันสร้างลิงค์ นอกจากนี้คุณไม่สามารถข้ามระบบไฟล์ดังนั้นการทำงานกับสื่อที่เมาท์อาจล้มเหลว

ฮาร์ดลิงก์นั้นคล้ายกับการย้ายหากคุณลบไฟล์ต้นฉบับในภายหลัง:

- name: Remove old file
  file:
    path: /path/to/source/file
    state: absent

ประโยชน์อีกอย่างคือการเปลี่ยนแปลงจะยังคงอยู่เมื่อคุณอยู่ในระหว่างการเล่น ดังนั้นหากมีคนเปลี่ยนแปลงแหล่งที่มาการเปลี่ยนแปลงใด ๆ จะปรากฏในไฟล์เป้าหมาย

ls -lคุณสามารถตรวจสอบจำนวนการเชื่อมโยงไปยังไฟล์ผ่านทาง จำนวนฮาร์ดลิงก์จะปรากฏถัดจากโหมด (เช่น rwxr-xr-x 2 เมื่อไฟล์มี 2 ลิงก์)


2
น่าเสียดายที่สิ่งนี้จะใช้ไม่ได้กับไดเรกทอรีเนื่องจากไม่อนุญาตให้ใช้ลิงก์อย่างหนักสำหรับไดเรกทอรี (((
Drew

1
คำตอบนี้ทำให้สมมติฐานเกี่ยวกับระบบเป้าหมายโดยเฉพาะว่าทั้ง src และ dest อยู่ในพาร์ติชันเดียวกัน สิ่งนี้อาจไม่จริงและดังนั้นจึงไม่ควรใช้คำตอบนี้
mikky

4

บรูซไม่ได้พยายามจัดทำปลายทางเพื่อตรวจสอบว่าจะย้ายไฟล์หรือไม่หากมีอยู่แล้ว เขาทำให้แน่ใจว่าไฟล์ที่จะย้ายมีอยู่จริงก่อนที่จะพยายาม mv

หากความสนใจของคุณเช่น Tom's คือการย้ายเฉพาะในกรณีที่ไฟล์นั้นไม่มีอยู่ฉันคิดว่าเราควรจะรวมการตรวจสอบของ Bruce เข้ากับส่วนผสม:

- 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

3

นี่คือวิธีที่ฉันทำให้มันทำงานได้สำหรับฉัน:

  Tasks:
  - name: checking if the file 1 exists
     stat:      
      path: /path/to/foo abc.xts
     register: stat_result

  - name: moving file 1
    command: mv /path/to/foo abc.xts /tmp
    when: stat_result.stat.exists == True

playbook ด้านบนจะตรวจสอบว่ามีไฟล์ abc.xts อยู่ก่อนที่จะย้ายไฟล์ไปยังโฟลเดอร์ tmp หรือไม่


3
when: stat_result.stat.exists == Trueไม่จำเป็นต้องใช้ แค่ใช้when: stat_result.stat.existsก็ดีพอ
kuttumiah

ฉันมักจะใช้เพราะฉันมักจะทำบางสิ่งบางอย่างเมื่อแฟ้มถูกไม่พบหรือ== True == False
eduprado

ตามหน้าเอกสารอย่างเป็นทางการของstat existsคุณสมบัติโมดูลจะส่งคืนbooleanค่า ดังนั้นถ้าคุณใส่when: stat_result.stat.existsที่จะตอบสนองเงื่อนไขหากไฟล์ที่มีซึ่งเหมือนกันwhen: stat_result.stat.exists == Trueแต่มีข้อความเพิ่มเติมและการตรวจสอบเงื่อนไขที่ไม่จำเป็น
kuttumiah

0

สิ่งนี้อาจดูเหมือน overkill แต่ถ้าคุณต้องการหลีกเลี่ยงการใช้โมดูลคำสั่ง (ที่ฉันทำเพราะการใช้คำสั่งไม่ใช่ idempotent) คุณสามารถใช้การรวมกันของการคัดลอกและไม่เก็บถาวร

  1. ใช้ tar เพื่อเก็บถาวรไฟล์ที่คุณต้องการ ถ้าคุณคิดว่าข้างหน้านี่มันสมเหตุสมผลจริงๆ คุณอาจต้องการชุดของไฟล์ในไดเรกทอรีที่กำหนด สร้างไดเร็กทอรีนั้นด้วยไฟล์ทั้งหมดและเก็บถาวรใน tar
  2. ใช้โมดูลที่ไม่เก็บถาวร เมื่อคุณทำเช่นนั้นพร้อมกับปลายทาง: และคำสำคัญ remote_src: คุณสามารถวางไฟล์ทั้งหมดของคุณไปยังโฟลเดอร์ชั่วคราวเพื่อเริ่มต้นด้วยจากนั้นแตกไฟล์เหล่านั้นตามที่คุณต้องการ

ไม่มี idempotence ในการเก็บถาวรกับ tar
Visit1985

0

คุณสามารถทำได้โดย -

การใช้คำสั่ง Ad Hoc

ansible all -m command -a" mv /path/to/foo /path/to/bar"

หรือคุณถ้าคุณต้องการที่จะทำมันโดยใช้ playbook

- name: Move File foo to destination bar
  command: mv /path/to/foo /path/to/bar

0

ฉันรู้ว่ามันเป็นหัวข้อเก่าอายุหลายปีแต่ฉันรู้สึกหงุดหงิดและสร้างบทบาทให้กับตัวเองเพื่อทำสิ่งนี้เพื่อดูรายการไฟล์โดยพลการ ยืดออกตามที่เห็นสมควร

main.yml

- name: created destination directory
  file:
    path: /path/to/directory
    state: directory
    mode: '0750'
- include_tasks: move.yml
  loop:
    - file1
    - file2
    - file3

move.yml

- 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

โปรดทราบว่าการลิงก์ฮาร์ดไดรฟ์นั้นดีกว่าในการคัดลอกที่นี่เนื่องจากเป็นการรักษาความเป็นเจ้าของและการอนุญาตโดยธรรมชาติ (นอกเหนือจากการไม่ใช้พื้นที่ดิสก์เพิ่มเติมสำหรับสำเนาไฟล์ที่สอง)


0

บน Windows: - name: Move old folder to backup win_command: "cmd.exe /c move /Y {{ sourcePath }} {{ destinationFolderPath }}"

ในการเปลี่ยนชื่อใช้คำสั่งrenameหรือrenแทน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.