質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

シェル

シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

Q&A

解決済

5回答

15050閲覧

C言語のソースからバックグラウンドでシェルを実行したい

psd0201

総合スコア32

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

シェル

シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

0グッド

2クリップ

投稿2016/03/16 13:19

編集2016/03/17 00:29

C言語のソースにてPingを複数ホストに送信し、応答がない場合にある操作を行うプログラムを作成しています。

RAWソケットを自作して送信して・・・とやってもいいのですが、ちょっと手間がかかりそうなので、system関数を使用してPingをシェルにお願いしようとしています。
方針としては

system("ping -c 5 192.168.100.1 > /tmp/pingresult1 &");
system("ping -c 5 192.168.100.2 > /tmp/pingresult2 &");
system("ping -c 5 192.168.100.3 > /tmp/pingresult3 &");

と実行し、/tmp/pingresultのファイルができたら中身を読んで「5 packets transmitted, 5 packets received, 0% packet loss」という表示をみて判定しようと思っています。
しかし、実際にやってみるとファイルの中身は、

PING 192.168.100.1 (192.168.100.1): 56 data bytes
64 bytes from 192.168.100.1: icmp_seq=0 ttl=64 time=4.721 ms

で終わっていたり、Pingの応答がない場合は中身が空っぽになっており、Pingの結果がすべてファイルに書かれていない状態となっています。
system関数でこのようなことはできないのでしょうか?


追記
同様のことをpingではなく、
system("(date >> /tmp/test ; sleep 1; date >> /tmp/test ; sleep 5; date >> /tmp/test)&");
としたところ、きちんとすべての処理が終わりました。
pingになにかあるような気がしてきました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

もう解決しているようですが、ひとつの案としてコメントしておきます。
もし3つのpingをバックグラウンドで同時ではなく、順次で良いのであれば popen を使うと楽かもしれません。

C

1fp = popen( "ping -c 5 192.168.11.1", "r" );

テンプファイルを作らなくて良いですし、制御も楽です。

投稿2016/03/17 04:24

ttyp03

総合スコア16996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

system("(/usr/bin/ping -c 5 192.168.100.1 > /tmp/pingresult1)&");
と、pingをフルパスで指定したら結果を正しく得ることができました。
busyboxのpingと通常のpingが混在している環境なのですが、それが原因・・・?

いろいろ勉強になりました。
皆様、ありがとうございました。

投稿2016/03/17 01:15

編集2016/03/17 01:21
psd0201

総合スコア32

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

シェルでバックグラウンド処理させるのではなく、forkなどでプログラム的にバックグラウンド処理させた方が制御しやすい気がします。

コード例

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <assert.h> 4#include <unistd.h> 5#include <sys/types.h> 6#include <sys/wait.h> 7 8pid_t bg_system(const char *command) 9{ 10 pid_t pid = fork(); 11 if(pid == 0) 12 { 13 printf("%s\n", command); 14 system(command); 15 exit(0); 16 } 17 assert(pid != -1); 18 return pid; 19} 20 21int main() 22{ 23 pid_t pid1 = bg_system("ping -c 5 192.168.11.1 > /tmp/pingresult1"); 24 pid_t pid2 = bg_system("ping -c 5 192.168.11.2 > /tmp/pingresult2"); 25 pid_t pid3 = bg_system("ping -c 5 192.168.11.3 > /tmp/pingresult3"); 26 waitpid(pid1, NULL, 0); 27 waitpid(pid2, NULL, 0); 28 waitpid(pid3, NULL, 0); 29 printf("\n"); 30 system("cat /tmp/pingresult1"); 31 printf("\n"); 32 system("cat /tmp/pingresult2"); 33 printf("\n"); 34 system("cat /tmp/pingresult3"); 35 return 0; 36}

※うちはBuffaloのルーターを使っているので192.168.11.*としていますが、適宜置き換えてください。

投稿2016/03/16 16:22

編集2016/03/16 16:25
catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

/tmp/pingresultのファイルができたら中身を読んで

pingコマンドがスタートした時点でファイルができてしまうので、すぐに読み込んでしまうとダメそう(早すぎる)ですね。例えば、実行するコマンドを以下のように変えて、/tmp/pingdone1 のファイルができてから /tmp/pingresult1 のファイルの中身を読むのはどうでしょうか?

c

1system("(ping -c 5 192.168.100.1 > /tmp/pingresult1; touch /tmp/pingdone1)&");

投稿2016/03/16 13:41

tatsuya6502

総合スコア2035

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

psd0201

2016/03/16 14:36

pingdoneが出来上がってからpingresultを読みに行くような処理にしたのですが、一向にpingdoneが出来上がりません。 参考になるかわかりませんが、psコマンドで見たら以下のような2つのプロセスが残っています。 /bin/sh -c (ping -c 5 192.168.100.1 > /tmp/pingresult1; touch /tmp/pingdone1) & ping -c 5 192.168.100.1
guest

0

ベストアンサー

こんにちは。

まだpingコマンドを実行中ということはないでしょうか?
pingコマンドが終了していなかった場合、出力がまだバッファに入っていてファイルへ書きだされていないかも知れません。


【追記】

同様のことをpingではなく、

(後略)

不思議ですね。
良く分からないのですが、お使いのlinuxでsystem()関数がスレッド・セーフなのかどうか、まず確認されてはどうでしょうか?
この辺情報が錯綜していて結論が見えませんでした。
Man page of SYSTEM→スレッドセーフ
catsforepawさんご提示のサイト→マルチスレッドでsystemは危険
シグナルについて→マルチスレッドでシグナルのブロックは要注意
鉄則3: マルチスレッドのプログラムでのforkはやめよう→10年以上前の古い情報ですが、システムの本質的な部分の話なので変わったならそれなりに情報がある筈。

linuxがマルチスレッドでのforkに対応したという積極的な情報が見つからなければ、マルチスレッドでforkするのは危険という感じがひしひしとします。

投稿2016/03/16 13:39

編集2016/03/17 01:26
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

psd0201

2016/03/16 14:39

読む処理をやめて、pingコマンドが開始してしばらくしてからbashで手動で見に行っても同様の結果となっていました。 途中でpingが止まってしまっているようなイメージを受けます。
Chironian

2016/03/16 15:00

手元のubuntuでやってみました。 10秒ちょっとかかりますが、それくらい待ってから、pingresult1を見ればちゃんと入ってました。(私の環境に192.168.100.*のノードはありません。) PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data. --- 192.168.100.1 ping statistics --- 5 packets transmitted, 0 received, 100% packet loss, time 4035ms
psd0201

2016/03/16 16:24

わざわざ試していただきありがとうございます。 私の環境でも、シングルスレッドのプログラムで同様のことをしたら結果はちゃんと入りました。 実装したい環境はこれとは別で、マルチスレッドのプログラムをLinux起動時に起動スクリプトで自動で起動するようにしているのですが、それがいけないのでしょうか?
catsforepaw

2016/03/16 23:22

横から失礼します。 マルチスレッドでsystem関数を呼び出すと問題を起こすことがあるみたいです。 以前Linux向けのシステムを作った際、Linuxに詳しい人がsystem関数はマルチスレッドだと問題があるということで同等の機能の関数を自作していました。そのときはシステム起動時(スレッド作る前)にforkして、その子プロセスにsystem関数を実行させるような感じでした。 Linuxについてはあまり深い知識はないのでちょっと検索してみたところ、このようなページが見つかりました。 → http://blog.livedoor.jp/centosnotes/archives/2783453.html 何か関係ありそうでしょうか。
otn

2016/03/17 01:31

> 実装したい環境はこれとは別で、マルチスレッドのプログラムをLinux起動時に起動スクリプトで自動で起動するようにしているのですが、 それはこの質問とは全く別の話なので、別途質問を投稿すべきでしょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問