• 締切済み

UNIXにおけるパイプラインの実現

C言語で簡単なシェルを作成しているのですがパイプラインの処理がいまいちわかりません(とりあえずpipeとfork,dupをつかって標準出力を切り替えるのはわかります。) 以下のような感じでps コマンドを使いプロセスの親子関係を調べてみました。 @ubuntu-desktop:~$ ps -l > a.txt | wc | nl 1 0 0 0 @ubuntu-desktop:~$ cat a.txt F S UID PID PPID CMD 0 S 1000 5214 5208 bash 0 R 1000 5295 5214 ps 0 R 1000 5296 5214 wc 0 S 1000 5297 5214 nl 結果的にコマンドが子で親がシェルになっているのはわかったんですが これはどのようにパイプラインでデータの受け渡しをしているのでしょうか??

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

何を質問しているのかがよくわからないんですけど.... 今の例だと, bash が 1. pipe 2. fork 3. dup 4. 子プロセスが ps を exec 以下, wc と nl に対して同じようなことを繰り返す という処理をしています. で最後の行に関していえば, 「pipe を発行したときにカーネルがこっそりとファイルを作っている」と思えばいいんじゃないかな.

poanta
質問者

補足

回答ありがとうございます、意味不明な質問ですいませんでした。 知りたい事としては、子プロセスの出力(コマンドの結果)をパイプで送る際の方法です。 親の標準入力につなげてしまうか、ファイルディスクリプタをとっておいて次のコマンドの子プロセスでそのファイルディスクリプタから前の結果を受け取るかの方法があるかなと考えたんですが、どっちの方がよいのかと 思い質問させていただきました。

関連するQ&A

  • ログインシェルと対話型シェルの区別について

    ログインシェルと対話型シェルの区別について理解していません。  ログインシェルはpsコマンドで見たときに-bashと表示されると書籍にありました。  テキストログイン(init 3)してpsコマンドをうっても-bashになっていません。  ご存知の方、いらっしゃいますでしょうか?

  • garbage errorの回避方法を教えて下さい

    シェル(bash)で、下記を実行すると、 ps auwxm | wc -l 実行時に、garbage errorとなります。 エラーを回避する方法を教えて下さい。 ARRAY=("ps auwxm" "ps auwxm | wc -l" "") CNT=0 while test "${ARRAY[CNT]}” != "" do ${ARRAY[CNT]} >> kekka.txt   CNT=`expr ${CNT} + 1` done

  • ターミナル: パイプラインで検索

    あるASCIIファイルに、 Name A B C D T.O 4 3 2 3 C.K 2 1 2 5 . . . というように名前とスコアが記入されていて、 このファイルから、 Dの点数が一番高かった人は誰で、 その人のAの点数は何番目だったか、 という操作パイプラインを使って一行のコマンドで実行したいのですが、うまくいきません。 自分で考えたのは、 ●Dの点数が一番高かった人 $ sort -k 5 -n -r exam | head -n 1 ●D点数が一番高かった人(をE.Tとすると)のAの順位 $ sort -k 2 -n -r exam | grep -B 101 E.T | wc -l という感じなのですがどうやって一緒にするのか分かりません… (全くやり方が違うかも知れないですが(^_^;)) どなたか教えてください(>_<)

  • awkでの出力項目の追加方法について

    はじめまして。 急遽UNIXサーバをメンテすることになったUNIX素人です。時間に迫られており勉強する時間も今はとれず、皆様のお知恵をお借りしたく質問させていただきます。 現在、コマンド出力結果などの各行の先頭に、日時分秒を追加してテキストファイル出力するシェルスクリプトの作成をしています。 awk を使用して実現したいと思っていますが、具体的な方法についてアドバイスをいただけたらと思っています。 なお、コマンド出力結果をawkへ引き渡す方法は、スクリプト内で直接渡しても、一旦ファイル出力したものを読み込む形のどちらでもよいと思っています。 例 ・ps の出力結果 PID PPID PGID WINPID TTY UID STIME COMMAND 1072 1 1072 1072 con 1005 10:41:29 /usr/bin/bash 1052 1072 1052 544 con 1005 10:50:14 /usr/bin/ps ・日時分秒 を追加した結果 DATE PID PPID PGID WINPID TTY UID STIME COMMAND 200705111735 1072 1 1072 1072 con 1005 10:41:29 /usr/bin/bash 200705111735 1052 1072 1052 544 con 1005 10:50:14 /usr/bin/ps 大変初歩的な質問で申しわけありませんが、なにどぞご教授お願いします。

  • UNIX上でのファイルopenについて

    C言語で同一ディレクトリから複数のファイルを順番に読み込んでいきたいのですが、うまくいきません。 シェルで、ファイル名の取得を行っていっています。 shell ---- ls /home/data > /home/src/infile.txt ---- C ----------------------------- FILE *fp; char y[30]="/home/data/"; // ↓aには上記シェルにて取得した1件目のファイル名が入っています。 strcat(y,a); // ↓ここでは絶対パスが正しく表示されます printf("ddd:%s\n",y); // ddd:/home/data/11.txt // ↓ここでfile open errorで一件目で終了してしまいます。 if ((fp = fopen(y,"r")) == NULL){ printf("file open error!!\n"); exit(1); } ----------------------------- このようなファイルの読込みのやり方ができるのか教えてください。 もしできるのであるのなら、そのやり方も教えてください。 わかりにくい文章ですが、お願いします。

  • Windows10のWSLへのペーストについて

    WindowsのWSLをいつもパワーシェルからbashコマンドで起動しています。その時点でウィンドウがubuntuのターミナルなりますが、ウィンドウズ上でコピーした文字をそのubuntuのターミナルにペーストすることは可能でしょうか。ctrl+Vとかctrl+shift+Vとかではできませんでした。右クリックなども効かないようです。よろしくお願いします。 以前はできたと思ったのですが、現在はできません。WSLではなくて、VMwareだったらできた思いますが、WSLよりも起動が遅くリソースを使ってそうなので敷居が高くなっているのでWSLにしたいのですが。

  • シェルの変数の動作についての質問

    solaris8上で、シェルから別のシェルを子プロセスを動作させて その子プロセスが終了したかを判定するシェルを作成しました。 そのシェルの抜粋は下記のようになっています。 ---------------------------------------------------- "コマンド実行" & PID=$! i=0 ERR_FLG=1 echo " PID="$PID >> tmp.txt   ・・・・(1) while [ 1 ] do   if [ `ps -ef | grep $PID | grep -v grep | wc | awk '{print $1}'` -eq 0 ]; then     ERR_FLG=0     break   fi   "終了条件を満たしたかを確認するサブルーチン"   if [ $? -eq 1 ]; then     echo "Time out" >> tmp.txt     break   fi   i=`expr $i + 1 `   sleep 10 done echo `ps -ef | grep $PID | grep -v grep` >> tmp.txt ・・・・(2) ---------------------------------------------------- 殆どの場合問題なく動作しているのですが、 ごく稀に、(1)と(2)で取得した$PIDの値が異なるという現象が起きます。 当然サブルーチン上で、PIDを書換する処理もありません。 どのような状況の時に、現象が起きるかもはっきりしていません。 この現象の回避方法が判る方がおられましたら御教示の程、 宜しくお願いします。

  • ファイル転送が完了したことを判定する

    UNIX上のシェルにて、大容量のファイル転送が完了したかどうか判定する方法はないでしょうか?test -r $対象ファイル をすると転送中でも読み取り可能となってしまい、ファイルが転送完了したか判断できません。wcコマンドやcatコマンドを使用すると一応エラーではかえってくるのですがそんな方法しかないのかな?と疑問を感じています・・・。

  • sedコマンドでのエスケープ文字の扱い

    はじめまして。Linuxのsedコマンドで困っています。 sedの置換文字列として連続する\をリテラルとする処理を考えていますが、\がいくつ入ってくるか(変数)、わからない場合において、複雑な処理なしに対処できないか、考えています。 ↓簡単な例ですが、コマンドベースで説明すると以下のようなものです。 $ var='\\' $ cat file.txt aa $ sed "s/.*/$var/" file.txt \ という結果になりますが、置換文字を変数から取る際に、連続する\が設定されるケースを想定したプログラムを組むたいと思っています。 \が入ってくる個数がわかるのであれば、\を2倍にセットしておけばできそうですが、いくつセットされてくるかはわからない場合、何かよい方法はないでしょうか。 念のため、Linux環境で、GNU sed 4.1.2版で試行しています。シェルはbashです。よろしくお願いします。

  • shellスクリプトに複数の引数を渡したい

    shellスクリプトに複数の引数を渡したいと考えています。 下記のようなperlスクリプトを兼ねる事でやりたいことは達成できました。 これをシェルスクリプトだけでやろうとしていて、ハマってしまい、やり方がわからなかったので、質問しています。 ・echo.shの中身 $ cat echo.sh echo $1 $2 ・imglist.plの中身 $ cat imglist.pl my@imglist= `ls -1 *{.gif,.bmp,.jpg,.jpeg,.png} 2>1&`; foreach(@imglist){ my@name=split /\./,$_; system("bash ./echo.sh $name[0] $name[1]"); } ・実行すると、無事echo.shに引数が2つ渡る。 $ perl imglist.pl abc1 jpg abc10 png abc11 png abc2 jpg abc3 jpg これをシェルのみでやろうとして、はまってしまいました。 以下は、パイプ処理等を使ったりしてやってみたのですが出来ませんでした。 ・awkでファイル名と拡張子に分解し、パイプで渡そうとしても何故か渡らない・・ $ ls -1 *{.gif,.bmp,.jpg,.jpeg,.png} | awk -F . '{print $1,$2}'| bash ./echo.sh ・ファイルに一旦保存し、catコマンドでパイプで渡しても駄目 $ ls -1 *{.gif,.bmp,.jpg,.jpeg,.png} | awk -F . '{print $1,$2}' > imglist.txt $ cat imglist.txt | bash ./echo.sh ・echoコマンドを使ってパイプで渡しても駄目 $ echo `cat imglist.txt` |bash ./echo.sh ・for.shというファイルを作成し、for構文でimglist.txtの中身を渡すと引数が一つずつしか渡らない $ cat for.sh for id in $(cat imglist.txt); do echo $id done $ bash for.sh tile1 jpg tile10 jpg どうやれば、コマンドライン上やシェルスクリプトだけで、今回はファイル名と拡張子という形で複数行からなる2つの引数を渡すことができますでしょうか

    • ベストアンサー
    • Perl