উত্তর:
কেমন:
prog1 & prog2 && fg
এটা হবে:
prog1
।prog2
এবং পুরোভূমিতে এটা রাখা , তাই আপনি এটি দিয়ে বন্ধ করে দিতে পারেন ctrl-c
।prog2
, আপনি ফিরে আসবেন prog1
'র ফোরগ্রাউন্ড , তাই আপনাকে আরো ঘনিষ্ঠ এটা দিয়ে করতে পারেন ctrl-c
।prog1
যখন prog2
বন্ধ? চিন্তা করুন node srv.js & cucumberjs
prog1 & prog2 ; fg
এটি একবারে একাধিক এসএস টানেল চালানোর জন্য। আশা করি এটি কাউকে সাহায্য করবে।
prog2
অবিলম্বে চলতে ব্যর্থ হয় তবে আপনি prog1
অগ্রভাগে ফিরে আসবেন । এটি যদি পছন্দসই হয় তবে ঠিক আছে।
prog1 & prog2 && kill $!
।
আপনি ব্যবহার করতে পারেন wait
:
some_command &
P1=$!
other_command &
P2=$!
wait $P1 $P2
এটি ভেরিয়েবলগুলিকে ব্যাকগ্রাউন্ড প্রোগ্রাম পিআইডি বরাদ্দ করে ( $!
এটি সর্বশেষ প্রবর্তিত প্রক্রিয়া 'পিআইডি), তারপরে wait
কমান্ডটি তাদের জন্য অপেক্ষা করে। এটি দুর্দান্ত কারণ আপনি যদি স্ক্রিপ্টটি হত্যা করেন তবে এটি প্রক্রিয়াগুলিকেও মারবে!
#!/usr/bin/env bash ARRAY='cat bat rat' for ARR in $ARRAY do ./run_script1 $ARR & done P1=$! wait $P1 echo "INFO: Execution of all background processes in the for loop has completed.."
${}
এটি একটি স্ট্রিং তালিকায় বা অনুরূপ মধ্যে ইন্টারপোলেট করতে আপনাকে ব্যবহার করতে হবে।
জিএনইউ সমান্তরাল http://www.gnu.org/software/parallel/ এর সাথে এটি সহজ:
(echo prog1; echo prog2) | parallel
বা আপনি যদি পছন্দ করেন:
parallel ::: prog1 prog2
আরও জানুন:
parallel
বিভিন্ন সিনট্যাক্স সহ বিভিন্ন সংস্করণ রয়েছে । উদাহরণস্বরূপ, ডেবিয়ান ডেরিভেটিভস moreutils
প্যাকেজে প্যাকেজে একটি আলাদা কমান্ড রয়েছে parallel
যা একেবারেই আলাদা আচরণ করে।
parallel
ব্যবহার বেশী ভালো &
?
parallel
কোরের তুলনায় আরও বেশি চাকরি থাকলে @ অপটিমাসপ্রাইম আরও ভাল হয়, এক্ষেত্রে কোর &
প্রতি একাধিক কাজ একবারে চালানো হবে। (সিএফ। পায়রাহোল নীতি )
আপনি যদি সহজেই একাধিক প্রক্রিয়াটি সহজে চালাতে ও মারতে সক্ষম হতে চান তবে ctrl-c
এটি আমার প্রিয় পদ্ধতি: একটি (…)
সাবশেলে একাধিক ব্যাকগ্রাউন্ড প্রক্রিয়া তৈরি করে এবং সম্পাদন SIGINT
করতে ট্র্যাপ kill 0
, যা সাব-শেল গ্রুপে তৈরি সমস্ত কিছুকে মেরে ফেলবে:
(trap 'kill 0' SIGINT; prog1 & prog2 & prog3)
আপনার জটিল প্রক্রিয়া সম্পাদন কাঠামো থাকতে পারে এবং সমস্ত কিছু একক দিয়ে বন্ধ হয়ে যাবে ctrl-c
(কেবল নিশ্চিত করুন যে শেষ প্রক্রিয়াটি অগ্রভাগে চালিত হয়েছে, অর্থাত্ &
পরে কোনওটি অন্তর্ভুক্ত করবেন নাprog1.3
):
(trap 'kill 0' SIGINT; prog1.1 && prog1.2 & (prog2.1 | prog2.2 || prog2.3) & prog1.3)
xargs -P <n>
আপনি চালানোর অনুমতি দেয় <n>
সমান্তরালভাবে কমান্ড ।
যদিও -P
একটি নন-মানসম্পন্ন বিকল্প, জিএনইউ (লিনাক্স) এবং ম্যাকোএস / বিএসডি বাস্তবায়ন উভয়ই এটি সমর্থন করে।
নিম্নলিখিত উদাহরণ:
time xargs -P 3 -I {} sh -c 'eval "$1"' - {} <<'EOF'
sleep 1; echo 1
sleep 2; echo 2
sleep 3; echo 3
echo 4
EOF
আউটপুটটি এমন দেখাচ্ছে:
1 # output from 1st command
4 # output from *last* command, which started as soon as the count dropped below 3
2 # output from 2nd command
3 # output from 3rd command
real 0m3.012s
user 0m0.011s
sys 0m0.008s
সময়টি দেখায় যে কমান্ডগুলি সমান্তরালভাবে চালিত হয়েছিল (শেষ কমান্ডটি মূল 3 টি প্রথম সমাপ্ত হওয়ার পরে শুরু হয়েছিল তবে খুব দ্রুত কার্যকর করা হয়েছিল)।
xargs
কমান্ড নিজেই ফিরে আসবে না যতক্ষণ না সব কমান্ড সমাপ্ত করেছেন, কিন্তু আপনার নিয়ন্ত্রণ অপারেটর সঙ্গে এটি সসীম দ্বারা পটভূমিতে এটা নির্বাহ করতে পারেন &
এবং তারপর ব্যবহার wait
builtin সমগ্র জন্য অপেক্ষা করতে xargs
হুকুম শেষ করতে।
{
xargs -P 3 -I {} sh -c 'eval "$1"' - {} <<'EOF'
sleep 1; echo 1
sleep 2; echo 2
sleep 3; echo 3
echo 4
EOF
} &
# Script execution continues here while `xargs` is running
# in the background.
echo "Waiting for commands to finish..."
# Wait for `xargs` to finish, via special variable $!, which contains
# the PID of the most recently started background process.
wait $!
বিঃদ্রঃ:
বিএসডি / ম্যাকোস xargs
আপনাকে সমান্তরালভাবে স্পষ্টভাবে চলতে কমান্ডের গণনা নির্দিষ্ট করতে হবে , যেখানে জিএনইউ xargs
আপনাকে সমান্তরালে যতটা সম্ভব-P 0
চালানোর জন্য নির্দিষ্ট করতে দেয় ।
সমান্তরালভাবে চালিত প্রক্রিয়াগুলি থেকে আউটপুট উত্পন্ন হওয়ার সাথে সাথে উপস্থিত হয় , সুতরাং এটি অনির্দেশ্যভাবে আন্তঃবিশ্বাস্য হবে ।
parallel
, যেমন ওলে এর উত্তরে উল্লিখিত হয়েছে ( বেশিরভাগ প্ল্যাটফর্মের সাথে স্ট্যান্ডার্ড আসে না ), প্রতিটি প্রক্রিয়া ভিত্তিতে আউটপুটটি সুবিধামত সিরিয়ালাইজ করে (গোষ্ঠীগুলি) দেয় এবং আরও অনেক উন্নত বৈশিষ্ট্য সরবরাহ করে।#!/bin/bash
prog1 & 2> .errorprog1.log; prog2 & 2> .errorprog2.log
পৃথক লগগুলিতে ত্রুটিগুলি পুনর্নির্দেশ করুন।
prog1 2> .errorprog1.log & prog2 2> .errorprog2.log &
ls notthere1 & 2> .errorprog1.log; ls notthere2 & 2>.errorprog2.log
। ত্রুটিগুলি কনসোলে যায় এবং উভয় ত্রুটি ফাইল খালি থাকে। @ ডেনিস উইলিয়ামসন &
যেমন বলেছেন যে বিভাজনকারী ;
, তেমনি (ক) কমান্ডের শেষে যেতে হবে (যে কোনও পুনর্নির্দেশের পরে), এবং (খ) আপনার একেবারেই দরকার নেই ;
:-)
একটি খুব দরকারী প্রোগ্রাম যা নোহুপকে কল করে।
nohup - run a command immune to hangups, with output to a non-tty
nohup
নিজেই ব্যাকগ্রাউন্ডে কিছু চালায় না, এবং ব্যাকগ্রাউন্ডে nohup
কাজগুলি চালনার জন্য প্রয়োজনীয়তা বা পূর্বশর্ত প্রয়োজন নয়। এগুলি প্রায়শই একসাথে দরকারী তবে যেমন প্রশ্নের উত্তর দেয় না।
সমান্তরালে সর্বোচ্চ এন প্রক্রিয়া চালানোর জন্য আমি এখানে একটি ফাংশন ব্যবহার করছি (উদাহরণে এন = 4):
max_children=4
function parallel {
local time1=$(date +"%H:%M:%S")
local time2=""
# for the sake of the example, I'm using $2 as a description, you may be interested in other description
echo "starting $2 ($time1)..."
"$@" && time2=$(date +"%H:%M:%S") && echo "finishing $2 ($time1 -- $time2)..." &
local my_pid=$$
local children=$(ps -eo ppid | grep -w $my_pid | wc -w)
children=$((children-1))
if [[ $children -ge $max_children ]]; then
wait -n
fi
}
parallel sleep 5
parallel sleep 6
parallel sleep 7
parallel sleep 8
parallel sleep 9
wait
যদি ম্যাক্স_চিল্ডেন কোরগুলির সংখ্যায় সেট করা থাকে তবে এই ফাংশনটি নিষ্ক্রিয় কোরগুলি এড়াতে চেষ্টা করবে।
wait -n
প্রয়োজন bash
4.3+ এবং এটি জন্য অপেক্ষা করতে যুক্তিবিজ্ঞান পরিবর্তন কোন নিদিষ্ট / উহ্য প্রক্রিয়ার বিনষ্ট।
আমার সম্প্রতি একইরকম পরিস্থিতি হয়েছিল যেখানে আমার একই সময়ে একাধিক প্রোগ্রাম চালানো দরকার ছিল, তাদের আউটপুটগুলিকে পৃথক লগ ফাইলগুলিতে পুনর্নির্দেশ করা উচিত এবং তাদের শেষ হওয়ার জন্য অপেক্ষা করছিলাম এবং আমি এরকম কিছু দিয়ে শেষ করেছি:
#!/bin/bash
# Add the full path processes to run to the array
PROCESSES_TO_RUN=("/home/joao/Code/test/prog_1/prog1" \
"/home/joao/Code/test/prog_2/prog2")
# You can keep adding processes to the array...
for i in ${PROCESSES_TO_RUN[@]}; do
${i%/*}/./${i##*/} > ${i}.log 2>&1 &
# ${i%/*} -> Get folder name until the /
# ${i##*/} -> Get the filename after the /
done
# Wait for the processes to finish
wait
সূত্র: http://joaoperibeiro.com/execute-m Multipleple-program-and-redirect-their-outputs-linux/
প্রক্রিয়া স্প্যানিং ম্যানেজার
অবশ্যই, প্রযুক্তিগতভাবে এগুলি প্রক্রিয়া, এবং এই প্রোগ্রামটিকে প্রকৃতপক্ষে একটি প্রক্রিয়া স্প্যানিং ম্যানেজার বলা উচিত, তবে এটি কেবল যখন এম্পারস্যান্ড ব্যবহার করে কাঁটাচামচ করে তখন এটি কাজ করে সেই পথেই এটি কাঁটা () বা সম্ভবত ক্লোন () সিস্টেম কল ব্যবহার করে যা pthread_create () এর মত স্মৃতি ভাগ করে নেওয়ার চেয়ে আলাদা মেমরি স্পেসে ক্লোন করে। যদি BASH পরবর্তীকে সমর্থন করে তবে প্রতিটি "মৃত্যুদন্ডের ক্রম" ঠিক একই রকম কাজ করবে এবং আরও দক্ষ মেমরির পদচিহ্ন অর্জনের সময় এটি প্রচলিত থ্রেড হিসাবে অভিহিত হতে পারে। কার্যকরীভাবে তবে এটি একইরকম হয় যদিও গ্লোবাল ভেরিয়েবলগুলি প্রতিটি কর্মী ক্লোনটিতে উপলব্ধ না হওয়ার কারণে কিছুটা জটিল হয়ে যায় তাই সমালোচনামূলক বিভাগগুলি পরিচালনা করতে আন্ত-প্রক্রিয়া যোগাযোগ ফাইল এবং মূল ফ্লক সেমফোরের ব্যবহার। অবশ্যই বেস থেকে প্রার্থনা করা এখানে প্রাথমিক উত্তর তবে আমি মনে করি যেন মানুষ তা জানে তবে কেবল এটি কাঁটাচামচ না করে বরং কী তৈরি হয়েছে তা পরিচালনা করতে চাইছেন এবং ভুলে যাবেন। এটি একটি একক সংস্থান অ্যাক্সেসের জন্য কাঁটাচামচ প্রক্রিয়াগুলির 200 টি দৃষ্টান্ত পরিচালনা করার একটি উপায় প্রদর্শন করে। স্পষ্টতই এটি ওভারকিল তবে আমি এটি লেখা উপভোগ করেছি তাই আমি চালিয়ে গেলাম। সেই অনুযায়ী আপনার টার্মিনালের আকার বৃদ্ধি করুন। আশা করি এটি আপনার কাজে লাগবে।
ME=$(basename $0)
IPC="/tmp/$ME.ipc" #interprocess communication file (global thread accounting stats)
DBG=/tmp/$ME.log
echo 0 > $IPC #initalize counter
F1=thread
SPAWNED=0
COMPLETE=0
SPAWN=1000 #number of jobs to process
SPEEDFACTOR=1 #dynamically compensates for execution time
THREADLIMIT=50 #maximum concurrent threads
TPS=1 #threads per second delay
THREADCOUNT=0 #number of running threads
SCALE="scale=5" #controls bc's precision
START=$(date +%s) #whence we began
MAXTHREADDUR=6 #maximum thread life span - demo mode
LOWER=$[$THREADLIMIT*100*90/10000] #90% worker utilization threshold
UPPER=$[$THREADLIMIT*100*95/10000] #95% worker utilization threshold
DELTA=10 #initial percent speed change
threadspeed() #dynamically adjust spawn rate based on worker utilization
{
#vaguely assumes thread execution average will be consistent
THREADCOUNT=$(threadcount)
if [ $THREADCOUNT -ge $LOWER ] && [ $THREADCOUNT -le $UPPER ] ;then
echo SPEED HOLD >> $DBG
return
elif [ $THREADCOUNT -lt $LOWER ] ;then
#if maxthread is free speed up
SPEEDFACTOR=$(echo "$SCALE;$SPEEDFACTOR*(1-($DELTA/100))"|bc)
echo SPEED UP $DELTA%>> $DBG
elif [ $THREADCOUNT -gt $UPPER ];then
#if maxthread is active then slow down
SPEEDFACTOR=$(echo "$SCALE;$SPEEDFACTOR*(1+($DELTA/100))"|bc)
DELTA=1 #begin fine grain control
echo SLOW DOWN $DELTA%>> $DBG
fi
echo SPEEDFACTOR $SPEEDFACTOR >> $DBG
#average thread duration (total elapsed time / number of threads completed)
#if threads completed is zero (less than 100), default to maxdelay/2 maxthreads
COMPLETE=$(cat $IPC)
if [ -z $COMPLETE ];then
echo BAD IPC READ ============================================== >> $DBG
return
fi
#echo Threads COMPLETE $COMPLETE >> $DBG
if [ $COMPLETE -lt 100 ];then
AVGTHREAD=$(echo "$SCALE;$MAXTHREADDUR/2"|bc)
else
ELAPSED=$[$(date +%s)-$START]
#echo Elapsed Time $ELAPSED >> $DBG
AVGTHREAD=$(echo "$SCALE;$ELAPSED/$COMPLETE*$THREADLIMIT"|bc)
fi
echo AVGTHREAD Duration is $AVGTHREAD >> $DBG
#calculate timing to achieve spawning each workers fast enough
# to utilize threadlimit - average time it takes to complete one thread / max number of threads
TPS=$(echo "$SCALE;($AVGTHREAD/$THREADLIMIT)*$SPEEDFACTOR"|bc)
#TPS=$(echo "$SCALE;$AVGTHREAD/$THREADLIMIT"|bc) # maintains pretty good
#echo TPS $TPS >> $DBG
}
function plot()
{
echo -en \\033[${2}\;${1}H
if [ -n "$3" ];then
if [[ $4 = "good" ]];then
echo -en "\\033[1;32m"
elif [[ $4 = "warn" ]];then
echo -en "\\033[1;33m"
elif [[ $4 = "fail" ]];then
echo -en "\\033[1;31m"
elif [[ $4 = "crit" ]];then
echo -en "\\033[1;31;4m"
fi
fi
echo -n "$3"
echo -en "\\033[0;39m"
}
trackthread() #displays thread status
{
WORKERID=$1
THREADID=$2
ACTION=$3 #setactive | setfree | update
AGE=$4
TS=$(date +%s)
COL=$[(($WORKERID-1)/50)*40]
ROW=$[(($WORKERID-1)%50)+1]
case $ACTION in
"setactive" )
touch /tmp/$ME.$F1$WORKERID #redundant - see main loop
#echo created file $ME.$F1$WORKERID >> $DBG
plot $COL $ROW "Worker$WORKERID: ACTIVE-TID:$THREADID INIT " good
;;
"update" )
plot $COL $ROW "Worker$WORKERID: ACTIVE-TID:$THREADID AGE:$AGE" warn
;;
"setfree" )
plot $COL $ROW "Worker$WORKERID: FREE " fail
rm /tmp/$ME.$F1$WORKERID
;;
* )
;;
esac
}
getfreeworkerid()
{
for i in $(seq 1 $[$THREADLIMIT+1])
do
if [ ! -e /tmp/$ME.$F1$i ];then
#echo "getfreeworkerid returned $i" >> $DBG
break
fi
done
if [ $i -eq $[$THREADLIMIT+1] ];then
#echo "no free threads" >> $DBG
echo 0
#exit
else
echo $i
fi
}
updateIPC()
{
COMPLETE=$(cat $IPC) #read IPC
COMPLETE=$[$COMPLETE+1] #increment IPC
echo $COMPLETE > $IPC #write back to IPC
}
worker()
{
WORKERID=$1
THREADID=$2
#echo "new worker WORKERID:$WORKERID THREADID:$THREADID" >> $DBG
#accessing common terminal requires critical blocking section
(flock -x -w 10 201
trackthread $WORKERID $THREADID setactive
)201>/tmp/$ME.lock
let "RND = $RANDOM % $MAXTHREADDUR +1"
for s in $(seq 1 $RND) #simulate random lifespan
do
sleep 1;
(flock -x -w 10 201
trackthread $WORKERID $THREADID update $s
)201>/tmp/$ME.lock
done
(flock -x -w 10 201
trackthread $WORKERID $THREADID setfree
)201>/tmp/$ME.lock
(flock -x -w 10 201
updateIPC
)201>/tmp/$ME.lock
}
threadcount()
{
TC=$(ls /tmp/$ME.$F1* 2> /dev/null | wc -l)
#echo threadcount is $TC >> $DBG
THREADCOUNT=$TC
echo $TC
}
status()
{
#summary status line
COMPLETE=$(cat $IPC)
plot 1 $[$THREADLIMIT+2] "WORKERS $(threadcount)/$THREADLIMIT SPAWNED $SPAWNED/$SPAWN COMPLETE $COMPLETE/$SPAWN SF=$SPEEDFACTOR TIMING=$TPS"
echo -en '\033[K' #clear to end of line
}
function main()
{
while [ $SPAWNED -lt $SPAWN ]
do
while [ $(threadcount) -lt $THREADLIMIT ] && [ $SPAWNED -lt $SPAWN ]
do
WID=$(getfreeworkerid)
worker $WID $SPAWNED &
touch /tmp/$ME.$F1$WID #if this loops faster than file creation in the worker thread it steps on itself, thread tracking is best in main loop
SPAWNED=$[$SPAWNED+1]
(flock -x -w 10 201
status
)201>/tmp/$ME.lock
sleep $TPS
if ((! $[$SPAWNED%100]));then
#rethink thread timing every 100 threads
threadspeed
fi
done
sleep $TPS
done
while [ "$(threadcount)" -gt 0 ]
do
(flock -x -w 10 201
status
)201>/tmp/$ME.lock
sleep 1;
done
status
}
clear
threadspeed
main
wait
status
echo
আপনার স্ক্রিপ্ট দেখতে হবে:
prog1 &
prog2 &
.
.
progn &
wait
progn+1 &
progn+2 &
.
.
ধরে নিচ্ছি আপনার সিস্টেমটি একবারে n জব নিতে পারে। একবারে কেবল n কাজ চালানোর জন্য অপেক্ষা করুন।
সঙ্গে bashj ( https://sourceforge.net/projects/bashj/ ), আপনি না শুধুমাত্র একাধিক চালানোর জন্য সক্ষম হওয়া উচিত প্রসেস (উপায় অন্যদের পরামর্শ) কিন্তু একাধিক থ্রেড এক জেভিএম আপনার স্ক্রিপ্টটি থেকে নিয়ন্ত্রণ হবে। তবে অবশ্যই এটির জন্য জাভা জেডিকে দরকার। থ্রেডগুলি প্রক্রিয়াগুলির চেয়ে কম সংস্থান গ্রহণ করে।
এখানে একটি কার্যকারী কোড:
#!/usr/bin/bashj
#!java
public static int cnt=0;
private static void loop() {u.p("java says cnt= "+(cnt++));u.sleep(1.0);}
public static void startThread()
{(new Thread(() -> {while (true) {loop();}})).start();}
#!bashj
j.startThread()
while [ j.cnt -lt 4 ]
do
echo "bash views cnt=" j.cnt
sleep 0.5
done
wait
! হ্যাঁ, ব্যাশে আপনি স্ক্রিপ্টের শিশু প্রক্রিয়াগুলির জন্য অপেক্ষা করতে পারেন।