การเรียกใช้ launchd เพื่ออ่านอาร์กิวเมนต์ของโปรแกรมอย่างถูกต้อง


18

ฉันมีสคริปต์เรียกใช้งานที่คำสั่งที่ฉันพยายามเรียกใช้นั้นมีข้อผิดพลาด (เห็นได้ชัดว่าไม่ใช่คำตอนนี้) บ่นเกี่ยวกับการใช้งานที่ไม่เหมาะสม

ข้อผิดพลาดเฉพาะที่ฉันได้รับคือข้อความการใช้งานคำสั่งที่ทิ้งลงในบันทึกของระบบ จากนี้ฉันอนุมานข้อมูลอื่น ๆ (เส้นทางไปยังคำสั่งเวลา ฯลฯ ) ในการวางแผนจะถูกแยกวิเคราะห์อย่างถูกต้องเพียงไม่ตัวเลือกคำสั่ง

หลังจากการใช้คำสั่งฉันมีหนึ่งบรรทัดสุดท้าย:

18/11/2013 09:30:00.101 com.apple.launchd.peruser.501: (fake.lable.seti[33833]) Exited with code: 1

แต่นั่นหมายถึง "ฉันออกโดยมีข้อผิดพลาด"

ฉันรู้ว่า launchd แยกคำสั่งออกจากตัวเลือกและในหน้า man จะบอกคุณเกี่ยวกับ ProgramArguments: "... โปรดทราบ: ผู้คนจำนวนมากสับสนโดยกุญแจนี้โปรดอ่าน execvp (3) อย่างระมัดระวังมาก! .. "

ฉันอ่าน execvp (3) และฉันก็ไม่มีปัญญาดังนั้นฉันจึงขอร้องคุณมาก ๆ

โดยปกติการรันคำสั่งจากเทอร์มินัลจะเป็นดังนี้:

/Library/Application\ Support/BOINC\ Data/boinccmd --host localhost --passwd gobbledygook --project http://setiathome.berkeley.edu/ update

มันทำงานได้ดี

และนี่คือวิธีที่ฉันแยกมันในส่วน Program / ProgramArguments ของ LaunchAgent plist ของฉัน:

<key>Program</key>
    <string>/Library/Application Support/BOINC Data/boinccmd</string>
<key>ProgramArguments</key>
    <array>
        <string>--host localhost</string>
        <string>--passwd gobbledygook</string>
        <string>--project http://setiathome.berkeley.edu/ update</string>
    </array>

(สำหรับบันทึกฉันเดิมมีเส้นทางที่จะ boinccmd \ หนีออกมา แต่ไม่ได้ผล Launchd หนีช่องว่างในเส้นทางสำหรับคุณ)

ฉันพยายามแยกข้อโต้แย้งลงไปอีก:

<key>Program</key>
    <string>/Library/Application Support/BOINC Data/boinccmd</string>
<key>ProgramArguments</key>
    <array>
        <string>--host</string>
        <string>localhost</string>
        <string>--passwd</string>
        <string>gobbledygook</string>
        <string>--project</string>
        <string>http://setiathome.berkeley.edu/</string>
        <string>update</string>
    </array>

แต่นั่นก็ไม่ได้ผลเหมือนกัน

เช่นเคยฉันแน่ใจว่าฉันขาดอะไรง่าย ๆ ไปเลย

ขอบคุณ


ตอบ:

บรรทัดแรกของ ProgramArguments ต้องเป็นพา ธ ไปยังโปรแกรม นี่คือสิ่งที่ทำให้ฉันสะดุดและแน่นอนว่า "... โปรดอ่านอย่างระมัดระวังมาก!!" ความคิดเห็น :) ฉันยังพบว่าฉันต้องแยกข้อโต้แย้งออกเป็นส่วน ๆ เมื่อฉันมีทุกอย่างในสถานที่สิ่งทั้งหมดที่ทำงานมีเสน่ห์ ขอบคุณมาก.

<key>Program</key>
    <string>/Library/Application Support/BOINC Data/boinccmd</string>
<key>ProgramArguments</key>
    <array>
        <string>/Library/Application Support/BOINC Data/boinccmd</string>
        <string>--host</string>
        <string>localhost</string>
        <string>--passwd</string>
        <string>gobbledygook</string>
        <string>--project</string>
        <string>http://setiathome.berkeley.edu/</string>
        <string>update</string>
    </array>

การแก้ไขขั้นสุดท้ายเพื่ออธิบายคำอธิบายที่เข้าใจง่ายว่าทำไมจึงเป็นเช่นนี้ดูคำอธิบายของ SirPavlova

~ W


การใช้ launchctl list com.label.plist ฉันเห็นได้ว่า launchd กำลังรับส่วนที่ถูกต้องของคำสั่งเพื่อรวมเข้าด้วยกัน ฉันคิดว่าอาจเป็นปัญหาที่เกี่ยวข้องกับ - แต่ดูเหมือนจะไม่
Woodgie

1
ฉันไม่ได้รับคำตอบสำหรับปัญหาของคุณ แต่ตัวอย่างแรกของคุณด้วย<string>--host localhost</string>จะไม่ทำงานแน่นอน โปรดจำไว้ว่าเมื่อคุณเขียนบรรทัดคำสั่งไปยังเชลล์มันไม่ทราบว่าส่วนหนึ่งของตัวเลือกและอะไรคืออาร์กิวเมนต์ปกติ - เพียงแค่แยกช่องว่างก่อนส่งอาร์กิวเมนต์ไปยังโปรแกรมที่กำลังทำงานอยู่ นอกจากนี้ยังอาจช่วยได้หากคุณต้องแสดงข้อผิดพลาดที่แน่นอนที่boinccmdรายงาน
Kevin Reid

แก้ไขโพสต์ของฉันเพื่อพูดในสิ่งที่ฉันเห็น ไม่ใช่ว่ามันจะเป็นความช่วยเหลือใด ๆ ! นอกจากนี้ฉันยังได้รับข้อผิดพลาดเดียวกันถ้าฉันแยกตัวเลือกในช่องว่างของพวกเขา ฉันเดาว่ามันคือ - มันทำให้เกิดปัญหาอย่างใด
Woodgie

1
ฉันจะลองใช้เพียงแค่โปรแกรมหรือโปรแกรม
วัตถุ

คำตอบ:


19

Programระบุคีย์ไฟล์เพื่อดำเนินการที่ & ProgramArgumentsคีย์ระบุข้อโต้แย้งซึ่งจะถูกส่งผ่านไปยังขั้นตอนการดำเนินการ การพูดอย่างเคร่งครัดคุณสามารถผ่านการขัดแย้งใด ๆ ที่คุณต้องการให้กระบวนการ แต่การประชุมคือคนแรกที่ควรจะเป็นชื่อที่กระบวนการถูกเรียกดังนั้นโปรแกรมส่วนใหญ่ไม่สนใจอาร์กิวเมนต์แรกของพวกเขา แฟ้มที่จะดำเนินการจะเห็นได้ชัดข้อมูลที่จำเป็น แต่ถ้า Programที่สำคัญคือจะหายไป launchd อ้างว่ามันมีค่าเช่นเดียวกับอาร์กิวเมนต์แรกในหมดจดเป็นความสะดวกสบายProgramArguments

ตัวอย่างแรกของคุณเริ่มต้น boinccmd & ให้อาร์กิวเมนต์ที่เทียบเท่ากับคำสั่งเทอร์มินัล

--host\ localhost --passwd\ gobbledygook --project\ http://setiathome.berkeley.edu/\ update

ซึ่งบอกว่า boinccmd ว่าคุณเรียกใช้มันเป็น "--host localhost" & ส่งต่อเพียงสองอาร์กิวเมนต์ที่แปลก

ตัวอย่างที่สองของคุณแยกอาร์กิวเมนต์ได้อย่างถูกต้อง แต่เมื่อ Eddie Kelley แนะนำให้ใส่อาร์กิวเมนต์ที่ด้านหน้า มันบอกว่า boinccmd ว่าคุณเรียกมันว่า "--host" จากนั้นผ่านไปอีกหกข้อโต้แย้ง boinccmd สามารถรับรู้ห้าคนสุดท้ายว่าเป็นสองตัวเลือก แต่ไม่รู้ว่าธุรกิจ "localhost" นั้นเกี่ยวกับอะไร เท่าที่ boinccmd สามารถบอกได้มันถูกเรียกใช้จากเทอร์มินัลเป็น

/Library/Application\ Support/BOINC\ Data/boinccmd localhost --passwd gobbledygook --project http://setiathome.berkeley.edu/ update

(บันทึก "--host" ที่ขาดหายไป)

boinccmd อาจเป็นหนึ่งในโปรแกรมส่วนใหญ่ที่ไม่สนใจว่าอาร์กิวเมนต์แรกของพวกเขาคืออะไรดังนั้นคุณอาจจะแค่เข้าไป<string>HELLO</string>ที่ส่วนหัวของProgramArgumentsอาร์เรย์ แต่มันอาจจะดีกว่าถ้าเอาProgramคีย์ออกทั้งหมด & เพียงแค่ใช้สิ่งนี้:

<key>ProgramArguments</key>
    <array>
        <string>/Library/Application Support/BOINC Data/boinccmd</string>
        <string>--host</string>
        <string>localhost</string>
        <string>--passwd</string>
        <string>gobbledygook</string>
        <string>--project</string>
        <string>http://setiathome.berkeley.edu/</string>
        <string>update</string>
    </array>

ดูเหมือนว่าจะเป็นการสำรองข้อมูลที่ไร้ความหมาย แต่บางโปรแกรมใช้สิ่งนี้เพื่อผลที่ดี: bash et al ทำหน้าที่เป็นเปลือกหอยเข้าสู่ระบบถ้าอาร์กิวเมนต์แรกของพวกเขาเริ่มต้นด้วย-และเป็นกลุ่มเข้าสู่โหมดการจำลองต่างๆถ้าอาร์กิวเมนต์แรกของมันคือedหรือแทนvivim


1
คุณโพสต์เมื่อฉันแก้ไขโพสต์หลักของฉัน! นี่คือคำอธิบายที่ดี ขอขอบคุณ.
Woodgie

1
ดีใจที่ได้รับความช่วยเหลือ :)
SirPavlova

@SirPavlova ความช่วยเหลือที่ดี! อย่างไรก็ตามมีเครื่องมือใดบ้างที่ช่วยให้ผู้ใช้สามารถแปลงการเรียกใช้คอนโซลเป็นรูปแบบที่สมบูรณ์ได้?
gaussblurinc

6

จากหน้า man สำหรับ exec (3) ดูเหมือนว่าอาร์กิวเมนต์โปรแกรมแรกควรเป็นพา ธ ไปยัง executable:

The execv(), execvp(), and execvP() functions provide an array of pointers to null-terminated strings
 that represent the argument list available to the new program.  The first argument, by convention,
 should point to the file name associated with the file being executed. The array of pointers must be
 terminated by a NULL pointer.

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


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

1
@ Woodgie ใช่ที่พบในโปรแกรม - ProgramArguments ของคุณไม่ถูกต้องมันต้องการชื่อพา ธ ของไฟล์ที่เรียกใช้งานได้
user151019

โอ้ OH! ฉันคิดว่าฉันเห็นตอนนี้ ลองทำดูสิ
Woodgie

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