วิธีทำให้สคริปต์ python ทำงานต่อไปเมื่อฉันปิดผงสำหรับอุดรู


19

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


1
nohupตรวจสอบ
phk

คำตอบ:


36

คุณมีสองตัวเลือกหลัก:

  1. nohupเรียกใช้คำสั่งด้วย การดำเนินการนี้จะยกเลิกการเชื่อมโยงจากเซสชันของคุณและปล่อยให้มันทำงานต่อไปหลังจากที่คุณยกเลิกการเชื่อมต่อ:

    nohup pythonScript.py

    โปรดทราบว่า stdout ของคำสั่งจะถูกผนวกเข้ากับไฟล์ชื่อnohup.outเว้นแต่คุณจะเปลี่ยนเส้นทาง ( nohup pythonScript.py > outfile)

  2. ใช้ Multiplexer tmuxหน้าจอเช่น สิ่งนี้จะช่วยให้คุณตัดการเชื่อมต่อจากเครื่องระยะไกล แต่จากนั้นในครั้งต่อไปที่คุณเชื่อมต่อหากคุณทำงานtmux attachอีกครั้งคุณจะพบว่าตัวเองอยู่ในเซสชันเดียวกัน คำสั่งจะยังคงทำงานอยู่ (คำสั่งจะยังคงทำงานต่อเมื่อคุณออกจากระบบ) และคุณจะสามารถดู stdout และ stderr ของมันได้ราวกับว่าคุณไม่ได้ออกจากระบบ:

    tmux 
    pythonScript.py

    เมื่อคุณเปิดตัวแล้วให้ปิดหน้าต่าง PuTTY จากนั้นเชื่อมต่ออีกครั้งในวันถัดไปทำงานtmux attachอีกครั้งและคุณจะกลับมาที่จุดเริ่มต้น


4
ทางเลือกสำหรับ 1 & 2: 1. disown2.screen
heemayl

มันอาจจะเป็นมูลค่าการกล่าวขวัญbyobuเสื้อคลุมรอบ tmux หรือหน้าจอ
bli

2

screenเครื่องมือพร้อมใช้งานสำหรับลินุกซ์ distros ทั้งหมดสนับสนุนนี้

หากต้องการติดตั้งให้รันapt-get install screenสำหรับ distros Linux ที่ใช้deb dnf install -y screenหรือyum install -y screenสำหรับ RPM ที่ใช้พื้นฐาน

ใช้:

$ screen

เริ่มเชลล์ใหม่ ในเชลล์นี้คุณสามารถเริ่มต้นสคริปต์ Python ของคุณ จากนั้นคุณสามารถกดCtrl+ Shift+ แล้วA Dมันจะแยกขั้วของคุณจากเปลือกที่ใช้สคริปต์ของคุณ นอกจากนี้สคริปต์ยังคงทำงานอยู่

screen -rเพื่อดูว่าสคริปต์ของคุณทำงานคุณสามารถโทรหา สิ่งนี้จะแนบเทอร์มินัลของคุณเข้ากับเชลล์อีกครั้งด้วยสคริปต์ Python ที่คุณปล่อยให้ทำงานอยู่เบื้องหลัง

UPD: ฟ็อกซ์กล่าวถึงหน้าจอการทำงานที่ไม่ดีกับ systemd แต่เราสามารถใช้ systemd ที่จะเริ่มต้นสคริปต์เช่นที่พวกเขากล่าวว่าในตัวอย่างเป็นทางการ

ตัวอย่างเช่นหากสคริปต์ของคุณเริ่มต้นโดย/usr/bin/myPythonScriptคุณสามารถสร้างไฟล์หน่วย Systemd เช่นนี้

$ cat /etc/systemd/system/myPythonScript.service

[Unit]
Description=MyPythonScript

[Service]
ExecStart=/usr/bin/myPythonScript

[Install]
WantedBy=multi-user.target

กว่าคุณสามารถเริ่มต้นสคริปต์นี้ # systemctl daemon-reload # systemctl start myPythonScript

หากคุณต้องการให้สคริปต์นี้เริ่มต้นโดยอัตโนมัติเมื่อระบบเริ่ม -

# systemctl enable myPythonScript

เมื่อใดก็ตามที่คุณสามารถดูว่าสคริปต์ทำงานอย่างไร

# systemctl status myPythonScript

โฆษณาที่คุณสามารถตรวจสอบบันทึกของสคริปต์ของคุณ

# journalctl -u myPythonScript -e


โปรดทราบscreenว่าไม่ได้เล่นอย่างแน่นอนsystemdในการกำหนดค่าเริ่มต้น ฉันไม่รู้ว่า Ubuntu ใช้systemdหรือไม่ แต่พฤติกรรมและวิธีแก้ปัญหาอาจคุ้มค่าที่จะกล่าวถึงในคำตอบของคุณ
Fox

1

กระบวนการส่วนใหญ่สามารถถูกหลอกได้ด้วยการเปลี่ยนเส้นทาง stdout, stderr, stdin (ไม่ใช่ descriptors ทั้งหมดที่จำเป็นต้องเปลี่ยนเส้นทางเสมอ) และใช้&โอเปอเรเตอร์ควบคุม

เห็นว่าping example.com 1>/dev/null &ทำงาน

แน่นอนว่าบางโปรแกรมมีความซับซ้อนและต้องการวิธีแก้ปัญหาตามที่ @terdon กล่าวถึง แต่ก็เป็นการดีที่จะรู้และใช้สิ่งที่เหมาะสมที่สุด

แก้ไข: ดังที่เขียนไว้ในคำตอบนี้จะฆ่าsystemdกระบวนการในการออกจากระบบ systemdกระบวนการฆ่าบางรุ่นในการออกจากระบบโดยค่าเริ่มต้นกระบวนการอื่นไม่ทำ พฤติกรรมนี้สามารถเปลี่ยนแปลงได้โดยการแก้ไข /etc/systemd/logind.conf โดยการตั้งค่าตัวเลือกต่อไปนี้ ตามที่เขียนไว้มันอาจแก้ปัญหาบางอย่างที่คุณอาจมีกับโซลูชันของ @ terdon

จากman logind.conf:

KillUserProcesses=

รับอาร์กิวเมนต์บูลีน กำหนดว่าควรฆ่ากระบวนการของผู้ใช้เมื่อผู้ใช้ออกจากระบบหรือไม่ หากเป็นจริงหน่วยขอบเขตที่สอดคล้องกับเซสชันและกระบวนการทั้งหมดภายในขอบเขตนั้นจะถูกยกเลิก หากเป็นเท็จขอบเขตคือ "ละทิ้ง" ดูที่ systemd.scope (5) และกระบวนการจะไม่ถูกทำลาย เริ่มต้นที่ "ใช่" แต่ดูตัวเลือกKillOnlyUsers=และKillExcludeUsers=ด้านล่าง

นอกเหนือจากกระบวนการเซสชันกระบวนการผู้ใช้อาจทำงานภายใต้หน่วยจัดการผู้ใช้ user @ .service ขึ้นอยู่กับการตั้งค่าอิทธิพลนี้อาจช่วยให้ผู้ใช้เรียกใช้กระบวนการที่เป็นอิสระจากช่วงการเข้าสู่ระบบของพวกเขา ดูคำอธิบายของenable-lingerในloginctl(1)

โปรดทราบว่าการตั้งค่าKillUserProcesses=yesจะทำลายเครื่องมือเช่นscreen(1) และtmux(1) เว้นแต่ว่าพวกเขาจะถูกย้ายออกจากขอบเขตเซสชัน ดูตัวอย่างในsystemd-run(1)

อ่านคำตอบที่เชื่อมโยงเพื่อหาข้อมูลเพิ่มเติม


1
สิ่งนี้จะส่งกระบวนการไปที่พื้นหลัง OP ต้องการปลดการเชื่อมต่อจากเซสชัน ssh จากระยะไกลและให้ดำเนินการต่อ สิ่งนี้จะไม่ช่วยในสถานการณ์เช่นนั้นการออกจากเซสชันระยะไกลจะหยุดคำสั่งแม้ว่าจะอยู่ในพื้นหลัง
terdon

@terdon คุณตรวจสอบแล้วว่าตัวอย่างของฉันใช้ได้หรือไม่ ฉันได้ตรวจสอบและใช้งานได้กับบางคำสั่งเนื่องจากฉันเขียนไว้ในคำตอบแล้ว
โฟมบิน

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

@terdon ตลกฉันได้ตรวจสอบเรื่องนี้ใน ArchLinux ท้องถิ่นที่เชื่อมต่อกับ PLD ระยะไกล กฎเดียวที่ใช้งานได้ตลอดเวลาคือ "โปรแกรมใช้งานisatty()และออกจากโปรแกรมหรือไม่หากไม่ใช่"
โฟมบิน

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