ใช้คำสั่งระบบแทน Bash builtin โดยไม่ระบุพา ธ เต็ม


17

ฉันใช้ Bash เป็นเชลล์เชิงโต้ตอบของฉันและฉันสงสัยว่ามีวิธีง่ายๆในการทำให้ Bash เรียกใช้คำสั่งระบบแทนคำสั่ง shell builtin ในกรณีที่พวกเขาทั้งสองใช้ชื่อเดียวกันร่วมกัน

ตัวอย่างเช่นใช้ระบบkill(จากutil-linux) เพื่อพิมพ์รหัสกระบวนการ (pid) ของกระบวนการที่ระบุชื่อ (es) แทนการส่งสัญญาณ:

$ /bin/kill -p httpd
2617
...

โดยไม่ระบุพา ธ แบบเต็มของคำสั่งระบบ Bash builtin จะถูกใช้แทนคำสั่งระบบ killbuiltin ไม่ได้มี-pตัวเลือกเพื่อให้คำสั่งล้มเหลว:

$ kill -p httpd
bash: kill: p: invalid signal specification

ฉันพยายามตอบที่ระบุไว้ในทำให้การใช้งานภายนอกทุบตี `คำสั่ง time` มากกว่าเปลือก builtinแต่ส่วนใหญ่ของพวกเขาทำงานเพียงเพราะtimeเป็นจริงเปลือกคำหลัก - ไม่เปลือกbuiltin

นอกเหนือจากการปิดการใช้งาน Bash builtin ชั่วคราวenable -n killแล้วทางออกที่ดีที่สุดที่ฉันเคยเห็นคือการใช้:

$(which kill) -p httpd

มีวิธีอื่นที่ง่ายกว่า (เกี่ยวข้องกับการพิมพ์น้อยกว่า) ในการดำเนินการคำสั่งภายนอกแทนเชลล์บิวด์อินหรือไม่?

โปรดทราบว่าkillเป็นเพียงตัวอย่างและฉันต้องการโซลูชันทั่วไปที่คล้ายกับวิธีที่คำนำหน้าด้วยcommandbuiltin ป้องกันไม่ให้ฟังก์ชันที่มีชื่อเดียวกันกับคำสั่งภายนอกทำงาน ในกรณีส่วนใหญ่ฉันมักจะชอบใช้ builtin version เพราะมันช่วยในการฟอร์กกระบวนการใหม่และบางครั้ง builtin ก็มีฟีเจอร์ที่คำสั่งภายนอกไม่มี


การล้อมรอบwhich killใน backticks (ไม่สามารถใส่ไว้ในความคิดเห็น) จะสั้นกว่าเล็กน้อย
abligh

@ จุดดีมาก ฉันใช้เวลาหลายปีในการฝึกฝนตัวเองเพื่อใช้ไวยากรณ์ "ใหม่" สำหรับการทดแทนคำสั่ง :)
Anthony G - ความยุติธรรมสำหรับโมนิก้า

@ ระดับสูง: FYI คุณสามารถใส่ "backticks" ลงในความคิดเห็นโดยนำหน้า backslashes (\) แต่มีเหตุผลที่จะติดกับ$(…)- เห็นนี้ , นี้และนี้
G-Man กล่าวว่า 'Reinstate Monica'

คำตอบ:


20

สมมติว่าenvอยู่ในเส้นทางของคุณ:

env kill -p http

envรันไฟล์เรียกทำงานที่ตั้งชื่อโดยอาร์กิวเมนต์แรกในสภาพแวดล้อมที่แก้ไข (อาจ) เช่นนี้ไม่ทราบหรือทำงานกับคำสั่งในตัวเชลล์

สิ่งนี้สร้าง cruft การควบคุมงานเชลล์บางตัว แต่ไม่ต้องพึ่งพาคำสั่งภายนอก:

exec kill -p bash &

execต้องใช้ไฟล์ปฏิบัติการเพื่อแทนที่เชลล์ปัจจุบันดังนั้นจึงไม่ต้องใช้บิวด์อินใด ๆ งานรันในพื้นหลังเพื่อให้คุณแทนที่เชลล์แบ็คกราวด์ที่แยกไว้ไม่ใช่เชลล์ปัจจุบันของคุณ


2
envเป็นคำตอบที่ถูกต้องชัดเจน IMHO
abligh

@abligh: คุณถูกต้องในความคิดเห็นในคำตอบที่ถูกลบของฉัน command -p cmdเรียกคำสั่งภายนอกไม่ได้zsh bash
cuonglm

6
(exec kill -p http)ทำให้งานเปลี่ยน sub-shell แทน shell ปัจจุบันของคุณและคุณไม่ต้องจัดการ cruft ของ job control
Michael Hoffman

1
@AththonyGeoghegan แน่นอน แต่envยังไม่รู้เกี่ยวกับเชลล์บิวด์เพราะมันไม่ใช่เชลล์ คุณจะได้รับผลกระทบเดียวกันกับniceหรือxargsหรือโปรแกรมอื่น ๆ เช่นนั้น
user253751

1

วิธีที่ง่ายที่สุดในการทำสิ่งที่คุณต้องการอาจเป็นการวางสาย

alias kill="/bin/kill"

ลงใน~/.bashrcไฟล์ของคุณ หลังจากนั้นแต่ละเข้าสู่ระบบใหม่ / อุทธรณ์ของทุบตีจะแปล "ฆ่า" /bin/killเป็น


ฉันคิดถึงชื่อแทนแล้วและนี่เป็นหนึ่งในวิธีแก้ปัญหาที่ระบุไว้ในคำถามที่ฉันเชื่อมโยงกับ แต่ฉันหวังว่าจะมีวิธีแก้ปัญหาแบบทั่วไป (คล้ายกับcommandโซลูชัน) แทนที่จะสร้างนามแฝงแยกต่างหากสำหรับคำสั่ง "เงา" แต่ละคำ ตอนนี้ฉันได้แก้ไขคำถามของฉันเพื่อให้ชัดเจนและชัดเจนยิ่งขึ้น ในกรณีส่วนใหญ่ฉันมักจะชอบใช้ builtin version เนื่องจากกระบวนการสามารถระบุโดยรหัสงานได้ ขอบคุณ
Anthony G - ความยุติธรรมสำหรับโมนิก้า

1

หากคุณรู้วิธีแก้ปัญหาที่ต้องใช้การพิมพ์บางอย่างและคุณต้องการวิธีแก้ปัญหาที่ต้องการการพิมพ์น้อยลงให้สร้าง:

runFile() { local cmd="$1"; shift; cmd="$(which "$cmd")" && "$cmd" "$@"; }

ตัวย่อที่ใช้ความพยายามตามปกติคือสิ่งที่คอมพิวเตอร์เก่ง


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

1

ในกรณีที่เฉพาะเจาะจงนี้คำสั่งpgrepคือการจับคู่ที่ตรงกับความต้องการ

ในความหมายทั่วไปฟังก์ชั่นการทำงาน จาก "คำสั่ง file":

fcmd(){ local a=$1; shift; $(which "$a") "$@"; }

โทรเป็น

fcmd kill -p httpd

แต่ถ้าคุณต้องการการพิมพ์น้อยลงไม่มีทางที่สั้นไปกว่านามแฝงที่ดี

จากแนวคิด "list pid" (lp):

alias lp='/bin/kill -p'

จากนั้นให้พิมพ์:

lp httpd

0

(ใน zsh) คุณสามารถเติมคำสั่งชื่อใด ๆ ด้วยเครื่องหมาย = เพื่อรับเวอร์ชันระบบแทนบิวอิน นี่เป็นวิธีที่สะดวกในการหลบเลี่ยงนามแฝงที่ทำให้สถานการณ์เลวร้ายลง

$ =kill -p httpd

1
ฉันลองมันด้วย Bash เวอร์ชั่น 4.3.30 และมันไม่ทำงาน ฉันไม่เคยเห็นไวยากรณ์แบบนี้มาก่อน คุณสามารถเพิ่มลิงค์ไปยังที่ที่บันทึกคุณสมบัตินี้ได้หรือไม่? ปกติฉันจะใส่คำนำหน้านามแฝงด้วยแบ็กสแลชเพื่อเรียกใช้คำสั่งเวอร์ชันที่ไม่ใช่นามแฝง
Anthony G - ความยุติธรรมสำหรับโมนิก้า

@ อันธพาลนี่อาจจะเป็นzshสิ่งเดียว ฉันจะใช้มันเป็นประจำ แต่ฉันจะตรวจสอบbashจากคอมพิวเตอร์ในวันพรุ่งนี้
Caleb

ฉันสงสัยว่าอาจเป็นเปลือกบางส่วนที่ฉันไม่คุ้นเคย (ฉันคุ้นเคยกับการทุบตีประและ csh เท่านั้น) มีคำตอบอื่น (ตั้งแต่ลบ) zshที่ทำงานเฉพาะสำหรับการเป็น ในขณะที่ฉันติดแท็กคำถามนี้ด้วยbashและใช้ในชื่อคุณควรเก็บคำตอบนี้ไว้เป็นผู้ใช้ zsh จะยังคงพบว่ามีประโยชน์
Anthony G - ความยุติธรรมสำหรับโมนิก้า

-1

คุณสามารถส่งรายงานข้อผิดพลาดเทียบกับkillmanpage ของคุณและถามว่าทำไมตัวเลือกนี้ถึงมีตัวเลือกที่ไม่ได้มาตรฐานซึ่งนำมาจากpkillและใช้pkillเมื่อใดก็ตามที่คุณต้องการรับคุณสมบัติจากpkill.

ถ้าคุณโทร:

pkill httpd

คุณหลีกเลี่ยงปัญหาที่คุณอธิบาย

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