アプリ版:「スタンプのみでお礼する」機能のリリースについて

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

A 回答 (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 をつけなくても、
子プロセスが中断されないことも確認。

# 意地になってます (^^;

この回答への補足

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

補足日時:2001/07/06 21:11
    • good
    • 0

> コンパイルエラーが出ます



nohup って、コマンドであって、関数ではないです。

  system("nohup スクリプト &");

です。スクリプトには、実行権限をつけておいてください。
    • good
    • 0
この回答へのお礼

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

お礼日時:2001/07/06 20:11

> systemを使った場合、もし、シェルスクリプト(子)が起動中に親プログラムが


> 終了してしまったら、シェルのほうは一緒に死んでしまうのでしょうか

これは unix でのプロセスの扱い方の話なので、呼び方には関係ないです。

代表的なところでいうと、sh は端末が切り離されたときに HUP シグナルが
発生します。そのスクリプトが sh で動くものであれば、親プロセスが
端末から切り離されてないと、親が終了したときには、その子供に SIGHUP が
通知されます。何も考えずに作っていれば子プロセスも終了します。

それを回避するには nohup コマンドを使います。

csh は HUP を含めたキーボードから発生するシグナルはバックグラウンドジョブ
には通知されません。なので、親プロセスが終了しても、子プロセスは
動きつづけます。

この回答への補足

回答ありがとうございます。
nohupコマンドっていうのがあるのですね。

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

補足日時:2001/07/06 19:15
    • good
    • 0

> 親プログラムとシェルスクリプトは同時に動作させたいと思ってます



ということは、シェルスクリプトに起動をかけたら、その終了を待たずに
プログラムは他の処理を続けて良い、ということですね。であれば、

  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);

という感じ。

この回答への補足

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

補足日時:2001/07/06 16:56
    • good
    • 0

ちょっと確認します。



1.シェルスクリプトはエラーを起こす可能性があるか?
2.シェルスクリプトはエラーの場合それを報告するか?
3.エラーの報告はstderrか?プロセスステータスか?
4.起動するプログラム(親)はシェルスクリプト(子)の終了を待つか?同時に動作するか?

仕様によってはsystem()では役立たずの場合もあります。

完全な制御が必要ならfork()+exec()でしょう。
場合によってはwait()を使ったりsignal()の制御も必要になります。

この回答への補足

1~3についてはエラーを起こす可能性はありません。
4については、親プログラムとシェルスクリプトは同時に動作させたいと思ってます。

fork()+exec()の使い方がわからないのですが、
具体的にどういうふうに使うのでしょうか?

補足日時:2001/07/06 13:28
    • good
    • 0

補足読みました。


シェルスクリプトと言うことでしたらa-kumaさんがご回答された様に、

system("xxx"); ・・・xxxはシェルスクリプト名、必要ならばパス付きで。

または、実行権が付いていなければ

system("sh xxx");

とかでしょうか。
また、こちらもa-kumaさんが書かれていますが、子プロセスとして動作させたり、プロセスをスクリプトに空け渡して実行させるとしたらfork + exec系を使用することになると思います。
    • good
    • 0
この回答へのお礼

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

お礼日時:2001/07/06 16:55

確かに少々あいまいですので補足をお願いいたします。


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

この回答への補足

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

補足日時:2001/07/06 11:52
    • good
    • 0

何も考えなくて良いのが system() かな。



#include <stdlib.h>

system("ls -la");

って感じ。

他には、fork()+exec系の関数 とか popen() を使う方法もあります。
system() に比べて、細かくコントロールできるとか、出来ることが
増えていると考えてください。

オンラインマニュアルにも載ってますよ。
    • good
    • 0
この回答へのお礼

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

お礼日時:2001/07/06 11:51

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています