วิธีรันคำสั่งหลาย ๆ ครั้งโดยใช้ bash shell


153

มีวิธีเรียกใช้คำสั่ง (เช่นps aux|grep someprocess) สำหรับnครั้งหรือไม่?

สิ่งที่ต้องการ:

run -n 10  'ps aux|grep someprocess'

ฉันต้องการใช้มันแบบโต้ตอบโปรดอย่าโพสต์สคริปต์

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


คำตอบ:


197

ฉันไม่คิดว่าคำสั่งหรือ shell builtin สำหรับสิ่งนี้มีอยู่เนื่องจากเป็นเซตย่อยเล็กน้อยของสิ่งที่ Bourne shell forloop ออกแบบและใช้คำสั่งเช่นนี้ด้วยตัวคุณเองจึงค่อนข้างง่าย

สำหรับ starters คุณสามารถใช้ dummy forloop:

for i in `seq 10`; do command; done

หรือเทียบเท่าตามคำแนะนำของ JimB โดยใช้ Bash builtin สำหรับสร้างลำดับ:

for i in {1..10}; do command; done

นี้ iterates สิบครั้งการดำเนินการcommandในแต่ละครั้ง - มันอาจจะเป็นท่อหรือชุดของคำสั่งคั่นด้วยหรือ; &&คุณสามารถใช้$iตัวแปรเพื่อทราบว่ามีการวนซ้ำใดบ้าง

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

#function run
run() {
    number=$1
    shift
    for i in `seq $number`; do
      $@
    done
}

การใช้งาน:

run 10 command

ตัวอย่าง:

run 5 echo 'Hello World!'

16
@mahatmanich, loop ไม่ใช่สคริปต์ ไม่มีอะไรขัดขวางคุณไม่ให้ใช้ ... ที่เทอร์มินัลเชิงโต้ตอบ
Zoredache

3
สายการบินแบบหนึ่งข้างบนนั้นเป็นวิธีมาตรฐานที่ทำได้และค่อนข้างง่าย ทำไมมันไม่ดีสำหรับคุณ คุณอาจจะถามคำถามผิดหรือเปล่า? อะไรคือเป้าหมายหลักของสคริปต์หรือการกระทำของคุณที่คุณต้องการทำซ้ำหลาย ๆ ครั้ง? อาจจะมีวิธีแก้ปัญหาที่ดีกว่านี้ถ้าเราทำให้ปัญหานั้นแตกต่างไป
Patkos Csaba

6
@mahatmanich - for เป็น bash ในตัวสำหรับการวนซ้ำ
JimB

3
@Eduardo Ivanec - FYI ทุบตีได้ในตัวช่วงเช่นseq: {1..10}
JimB

1
ดูเหมือนว่าลำดับวงเล็บ inbuilt ไม่รองรับการทดแทนตัวแปร (ดูstackoverflow.com/a/3737773/713554 ) ฟังก์ชั่นที่คุณมอบให้ทำงานได้อย่างสมบูรณ์แบบเมื่อวางใน.bashrcหาก{1..$number} มีการแลกเปลี่ยน`seq $number`แม้ว่า
Leo

29

ps aux | grep someprocessดูเหมือนว่าคุณต้องการดูการเปลี่ยนแปลงของโปรแกรมในเวลาที่กำหนด Eduardo ให้คำตอบที่ตอบคำถามของคุณอย่างแน่นอน แต่มีทางเลือกอื่นwatch::

watch 'ps aux | grep someprocess'

โปรดทราบว่าฉันได้ใส่คำสั่งในราคาเดียวที่จะหลีกเลี่ยงเปลือกจากการตีความคำสั่งว่า "วิ่งนาฬิกา PS aux" grep someprocessและท่อผลผ่าน อีกวิธีในการทำคำสั่งก่อนหน้าคือ:

watch ps aux \| grep someprocess

โดยค่าเริ่มต้นwatchรีเฟรชทุกสองวินาทีที่สามารถเปลี่ยนแปลงได้โดยใช้-nตัวเลือก ตัวอย่างเช่นหากต้องการมีช่วงเวลา 1 วินาที:

watch -n 1 'ps aux | grep someprocess'

21

แค่เล่น ๆ

pgrep ssh ;!!;!!;!!;!!;!!;!!

ใครช่วยอธิบายเรื่องนี้ได้มั้ย ดูน่าสนใจมาก
Daniel Vartanov

4
; เป็นเพียงตัวคั่นคำสั่ง !! เล่นซ้ำคำสั่งสุดท้ายในทุบตี ดังนั้นเรียกใช้ 'pgrep ssh' แล้วเล่นซ้ำ 6 ครั้ง
Piotr Kukielka

ในขณะที่ให้คำแนะนำไม่ได้ใช้งานง่ายมาก หนึ่งซับforดูเหมือนว่าวิธีที่ดีที่สุด อย่างไรก็ตามขอขอบคุณสำหรับคำตอบ
erm3nda

1
cmd ;!!ในหนึ่งบรรทัดจะไม่ทำซ้ำคำสั่งที่ป้อนก่อนบรรทัดปัจจุบันหรือไม่ มันจะต้องเป็นสองhistoryรายการแยกต่างหาก
Joel Purra

แทนที่;ด้วย&&เพื่อหยุดในความล้มเหลวครั้งแรก
user881300

16

คล้ายกับคำตอบก่อนหน้า แต่ไม่จำเป็นต้องมีการวนรอบ:

seq 10 | xargs -I -- echo "hello"

ไพพ์เอาต์พุตของ seq ถึง xargs โดยไม่มีอาร์กิวเมนต์หรือตัวเลือก


2
echo "hello" 1 2 3 4 5 6 7 8 9 10เพียงแค่นี้ก็จะทำอย่างใดอย่างหนึ่งการดำเนินการ คุณจำเป็นต้องใช้ xargs กับ-n 1กระบวนการหนึ่งสำหรับแต่ละอินพุท (จำนวน) และ-P 10สำหรับการดำเนินการแบบคู่ขนาน (10 กระบวนการขนาน) seq 10 | xargs -n 1 -P 10 echoสิ้นสุดกับ
Alexander Klimetschek

16

ลองสิ่งนี้:

yes ls | head -n5 | bash

สิ่งนี้ต้องการคำสั่งที่จะดำเนินการใน sub-shell ซึ่งเป็นโทษประสิทธิภาพเล็กน้อย YMMV โดยทั่วไปคุณจะได้รับคำสั่ง "ใช่" เพื่อทำซ้ำสตริง "ls" N ครั้ง; ในขณะที่ "head -n5" ยกเลิกการวนซ้ำที่ 5 ซ้ำ ไพพ์สุดท้ายส่งคำสั่งไปยังเชลล์ที่คุณเลือก

cshเปลือกที่มีลักษณะเหมือนโดยบังเอิญมีrepeatคำสั่งในตัว คุณสามารถใช้มันเพื่อรันคำสั่งของคุณใน bash sub-shell!


5

วิธี POSIX

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04_01

x=10
while [ $x -gt 0 ]; do
    command
    x=$(($x-1))
done

ซึ่งแน่นอนสามารถทำให้เป็นหนึ่งซับ:

x=10; while [ $x -gt 0 ]; do command; x=$(($x-1)); done

และดูเหมือนจะเป็นวิธีพกพามากที่สุดและทำให้มีโอกาสน้อยที่จะทำให้คุณติดตั้งโปรแกรม

ต่อไปนี้เป็นแบบพกพาน้อย:

  • การขยายรั้ง{1..10}: ทุบตีเฉพาะและจะสร้างสายใหญ่ถ้าอาร์กิวเมนต์มีขนาดใหญ่
  • seq: GNU
  • yes: GNU

และถ้าคุณเบื่อกับการพกพาให้พิจารณา GNU parallel:

sudo apt-get install parallel
seq 100 | parallel echo {}

ซึ่งรันคำสั่งแบบขนานและมีตัวเลือกที่ยอดเยี่ยมมากมาย

ดูเพิ่มเติมที่: https://stackoverflow.com/questions/169511/how-do-i-iterate-over-a-range-of-numbers-defined-by-variables-in-bash


GNU Parallel นั้นถูกสร้างขึ้นให้พกพาสะดวก sh, zsh, kshและbashได้รับการสนับสนุนอย่างดีบนแพลตฟอร์มส่วนใหญ่ csh, tcsh, fishมีการสนับสนุน การใช้parallel --embedคุณสามารถสร้างสคริปต์ที่สามารถย้ายไปยังระบบอื่นซึ่งไม่ได้ติดตั้ง GNU Parallel ได้อย่างง่ายดาย
Ole Tange


0

นั่นคือ 'ระวัง' - ควรเป็นส่วนหนึ่งของระบบยูนิกซ์เกือบทุกระบบที่ใช้ procps

คุณสามารถเห็นการเปลี่ยนแปลง fs หรือการเคลื่อนไหวที่น่าสนใจในระบบ ตัวอย่างเช่น,

watch "df -hP | grep /tmp" 

เพียงใส่คำสั่งของคุณเป็นอาร์กิวเมนต์ (ดูman watch)


มีคำตอบอยู่กับนาฬิกาแล้ว ... ดูด้านล่าง ...
mahatmanich

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