次のタスクを実行するきれいでエレガントな方法を知りたいです。foo
というシェルスクリプトの一部として内部的に実行されるC ++プログラムを書いているとしましょうbar.sh
。シェルスクリプトをfoo
バックグラウンドプロセスとして実行し、待機したい。~まで実行がfoo
選択した行に達したら、bar
実行を続行する必要があります。
明確にするために、以下はダミーの例ですbar.sh
。
#!/bin/bash
./foo
wait
echo "WAKING UP"
これはfoo
:
#include <iostream>
int main(){
for (int i = 0; i < 1000000; i++){
std::cout << i << std::endl;
if (i == 50){
//Wake up bash!
}
}
}
waitコマンドが繰り返し50で停止するようにfoo
修正したいと思います。したがって、forループがに達すると目を覚ましてWAKING UPを印刷する必要があります。もちろん、走り続けることもできます。bar
bar
foo
foo
i = 50
bar
foo
この効果を得るには、これらのプログラムをどのように修正する必要がありますか?
答え1
fork()
これが基本的に+の意味ですsetsid()
。
bar.sh
#!/bin/bash
echo "Launching foo"
./foo
echo "Waking up"
foo.c
#include <stdio.h>
#include <unistd.h>
int main(int ac, char ** av)
{
int pid;
for (int i=0; i<5; i++) {
sleep(1);
}
printf("OK, we count to 5.\n");
/*
* Here we fork() + setsid() to detach from parent process
* Return value of fork is 0 if you are in child, pid of the child
* if you're in the parent process
*/
pid = fork();
if (pid == 0) {
setsid();
printf("We forked, still running but shell may be back\n");
sleep(5);
printf("Exiting ...\n");
} else {
return 0;
}
}
結果
/tmp/pouet$ ps aux|grep foo
me 8595 0.5 0.1 217548 18576 pts/12 T 14:17 0:01 vim foo.c
me 9167 0.0 0.0 12716 912 pts/12 S+ 14:21 0:00 grep foo
/tmp/pouet$ ./bar.sh
Launching foo
OK, we count to 5.
We forked, still running but shell may be back
Waking up
/tmp/pouet$ ps aux|grep foo
me 8595 0.5 0.1 217548 18576 pts/12 T 14:17 0:01 vim foo.c
me 9189 0.0 0.0 4160 76 ? Ss 14:21 0:00 ./foo
me 9192 0.0 0.0 12716 940 pts/12 S+ 14:21 0:00 grep foo
/tmp/pouet$ Exiting ...
/tmp/pouet$ ps aux|grep foo
me 8595 0.5 0.1 217548 18576 pts/12 T 14:17 0:01 vim foo.c
me 9212 0.0 0.0 12716 908 pts/12 S+ 14:21 0:00 grep foo
答え2
一つの方法は、fork
最初に両親を離れることです。
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
int main(){
for (int i = 0; i < 1000000; i++){
std::cout << i << std::endl;
if (i == 50){
if (fork() != 0) {
_Exit(0);
}
}
}
}
これは望ましくない効果を引き起こす可能性があり、_Exit
その中で最も確実なものはisを使用して回避できます。
もう1つの方法は、C ++プログラムが親プログラムにシグナルを送信することです。これはまた組み込み待機を終了します(POSIXか、単にbashismであるか覚えていません)。
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
int main(){
for (int i = 0; i < 1000000; i++){
std::cout << i << std::endl;
if (i == 50){
kill(getppid(), SIGINT);
}
}
}
ここで注目すべき点は、スクリプトとC ++プログラム間のプロセスです。trap
シェルスクリプトでシグナルを処理する方法を見つけたい場合があります。