• ベストアンサー

C++でシェルを起動

UNIX C++でシェルを起動する方法を教えてください。 よくわかっていないので、質問の仕方もあいまいですが、お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.8

> プログラムで上記のようにして実行しても、親プロセスが死んじゃうと、一緒に死んじゃうみたいです。 変だなあ。試してみたんだけど、大丈夫なんだよなあ。試したソースと スクリプトを。 親のソース。 #include <stdlib.h> int main() {   system("nohup a.sh &");   return 0; } 呼ばれるスクリプト。 #!/usr/bin/sh sleep 5 echo "aaa" >> aaa.txt で、chmod u+x a.sh して、a.sh に実行権限をつけて、 $ a ってして、5秒のうちに急いでログアウトする。子プロセスの a.sh は 中断されず aaa.txt に出力されている。 system() に渡すコマンドラインから nohup を外すと、子プロセスが 中断されることも確認。 また、ログインシェルを csh にしたら nohup をつけなくても、 子プロセスが中断されないことも確認。 # 意地になってます (^^;

noname#794
質問者

補足

ためしに、スクリプトを上記のやつで実行してみたら、ちゃんと動いてるみたいです。 シェルの中身が悪いんですかね。 よくわかりませんが、とりあえず、プログラムのほうは大丈夫みたいです。 ありがとうございました。

その他の回答 (7)

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.7

> コンパイルエラーが出ます nohup って、コマンドであって、関数ではないです。   system("nohup スクリプト &"); です。スクリプトには、実行権限をつけておいてください。

noname#794
質問者

お礼

回答ありがとうございました。 コマンドラインでコマンドを実行するときはいいみたいなのですが、 プログラムで上記のようにして実行しても、親プロセスが死んじゃうと、一緒に死んじゃうみたいです。 他の方法を試してみたいと思います。

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.6

> systemを使った場合、もし、シェルスクリプト(子)が起動中に親プログラムが > 終了してしまったら、シェルのほうは一緒に死んでしまうのでしょうか これは unix でのプロセスの扱い方の話なので、呼び方には関係ないです。 代表的なところでいうと、sh は端末が切り離されたときに HUP シグナルが 発生します。そのスクリプトが sh で動くものであれば、親プロセスが 端末から切り離されてないと、親が終了したときには、その子供に SIGHUP が 通知されます。何も考えずに作っていれば子プロセスも終了します。 それを回避するには nohup コマンドを使います。 csh は HUP を含めたキーボードから発生するシグナルはバックグラウンドジョブ には通知されません。なので、親プロセスが終了しても、子プロセスは 動きつづけます。

noname#794
質問者

補足

回答ありがとうございます。 nohupコマンドっていうのがあるのですね。 ちょっとプログラムに組み込んでみたのですが、コンパイルエラーが出ます。 "「nohup」にはプロトタイプが必要です"というエラーです。 あと確認したいのですが、このコマンドは引数はひとつしか渡せない?? この認識はあってますか?

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.5

> 親プログラムとシェルスクリプトは同時に動作させたいと思ってます ということは、シェルスクリプトに起動をかけたら、その終了を待たずに プログラムは他の処理を続けて良い、ということですね。であれば、   system("スクリプト &"); と、バックグラウンドジョブで起動すればOK。 > fork()+exec()の使い方がわからないのですが fork() は以下のように使います。   pid_t pid;   pid = fork();   if (pid == 0) {     execl("スクリプト", NULL);   } else if (pid < 0) {     /* fork() に失敗! */   } exec系の関数はいろいろありますので、man を参照してください。 例えば、私が最初に挙げたような ls -la をしたければ、execl() なら execl("/usr/bin/ls", "-la", NULL); と使います。execv() なら char *argv[3] = {"/usr/bin/ls", "-la", NULL}; execv("/usr/bin/ls", argv); と使います。 execle() と execve() は、更に環境変数の指定が出来ます。 execlp() と execvp() は、最初の引数に "/" が入っていなければ、 環境変数 PATH を利用した検索も行ないます。例えば、 execlp("ls", "-la", NULL); という感じ。

noname#794
質問者

補足

systemを使った場合、もし、シェルスクリプト(子)が起動中に親プログラムが終了してしまったら、シェルのほうは一緒に死んでしまうのでしょうか。 できれば、子は親に関係なく起動していてほしいのですが。 その場合はfork()+exec()のほうで起動すればなんとかなるものなのでしょうか。

  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.4

ちょっと確認します。 1.シェルスクリプトはエラーを起こす可能性があるか? 2.シェルスクリプトはエラーの場合それを報告するか? 3.エラーの報告はstderrか?プロセスステータスか? 4.起動するプログラム(親)はシェルスクリプト(子)の終了を待つか?同時に動作するか? 仕様によってはsystem()では役立たずの場合もあります。 完全な制御が必要ならfork()+exec()でしょう。 場合によってはwait()を使ったりsignal()の制御も必要になります。

noname#794
質問者

補足

1~3についてはエラーを起こす可能性はありません。 4については、親プログラムとシェルスクリプトは同時に動作させたいと思ってます。 fork()+exec()の使い方がわからないのですが、 具体的にどういうふうに使うのでしょうか?

  • natural
  • ベストアンサー率37% (419/1115)
回答No.3

補足読みました。 シェルスクリプトと言うことでしたらa-kumaさんがご回答された様に、 system("xxx"); ・・・xxxはシェルスクリプト名、必要ならばパス付きで。 または、実行権が付いていなければ system("sh xxx"); とかでしょうか。 また、こちらもa-kumaさんが書かれていますが、子プロセスとして動作させたり、プロセスをスクリプトに空け渡して実行させるとしたらfork + exec系を使用することになると思います。

noname#794
質問者

お礼

なんだか、難しそうですね。 ちょっと挑戦してみます。

  • natural
  • ベストアンサー率37% (419/1115)
回答No.2

確かに少々あいまいですので補足をお願いいたします。 ここで言うシェルとは仮想端末としてのシェルですか? それともシェルスクリプトですか? (後者ではないかと予想はしていますが) それによって回答は変わってくると思いますので。

noname#794
質問者

補足

シェルスクリプトのほうです。

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

何も考えなくて良いのが system() かな。 #include <stdlib.h> system("ls -la"); って感じ。 他には、fork()+exec系の関数 とか popen() を使う方法もあります。 system() に比べて、細かくコントロールできるとか、出来ることが 増えていると考えてください。 オンラインマニュアルにも載ってますよ。

noname#794
質問者

お礼

早速回答ありがとうございます。 ちょっと調べてみたいと思います。