68user's page 掲示板

Prev< No. 4513〜4606> Next  [最新発言に戻る] [過去ログ一覧]
No. 4514 # ロー 2006/02/11 (土) 18:39:14
UNIXのシェルで2点教えて頂きたいことがあります。

●1点目
sedコマンドを使用して置換したいのですが、sed内で変数は
使用可能なのでしょうか。

-----------------
#!/bin/sh

DIR="/home/guest/"
ls ${DIR}*.CSV | sed 's/$DIR}//g'

置換されずにそのまま出力されます。
シェル内の変数を、sedに渡して置換させることは可能なのでしょうか。

ls ${DIR}*.CSV | sed 's/\/.*\///g'
削除した部分がディレクトリと言う事なので、「's/\/.*\///g'」として
みたのですが、正しい使い方なのでしゅか。

●2点目
変数に格納されているファイル名から番号が一番大きいファイル名
を作りたいのですが、awkを使用して簡単にできますか。

例えば、/tmp配下に、
test0001.CSV
test0002.CSV
test0004.CSV
とファイルがあるとします。
ls、変数に格納し、awk等で、「test0005.CSV」を求めたいのですが。

---------
#!/bin/sh

FileLst=`ls /tmp/*.CSV`
echo $FileLst | awk ?????

No. 4515 # ロー 2006/02/11 (土) 18:41:13
>>4514 ロー
環境を書き忘れました。

UNIX:Soralis8
シェル:Bシェル

No. 4516 # 68user 2006/02/13 (月) 11:45:19
UNIX の部屋 http://x68000.q-e-d.net/~68user/unix/ を更新しました。

>>4460 mkt
> ・fgrep と Gimp の解説文が途中で切れてしまっているように思います。
fgrep については、とりあえず掲示板での発言にリンクを張りました。
    http://x68000.q-e-d.net/~68user/unix/pickup?fgrep

> ・記号の 2 項目め(「"」の項と思われる部分)の見出し行が抜け落ちてしまってます。
正しく表示されるようにしました。
    http://x68000.q-e-d.net/~68user/unix/pickup?%22

" の解決のため、10年近くつぎはぎでやってきた汚い部分を全面的に見直し
たため、もしかしたら UNIX の部屋の検索部分にエンバグしている可能性が
あります。怪しい挙動を見つけられた方は教えていただけると幸いです。

>>4501 hidemaru
> SSLv3のハンドシェイク処理の部分を実際に(Cで)実現する方法
>>4502 hidemaru
> 環境は、vine linux 、 openssl-0.9.7d-0vl3.2 です。
OpenSSL を使っていいなら SSL_connect(3) を使えばいいですし、OpenSSL を
使わないなら「環境は OpenSSL」とわざわざ書く理由がわからないです。

>>4508 dynamite
> SSL_shutdown()で0を返しERR_print_errors_fp には何も出力しないと
> 推測しているのですが
わたしもよくわかってませんが調べる時間がないです。すみません。
マニュアルにそう書いてありますか?

>>4511 blueeyes
> 本来welcome to hostname のところは今welcome to 1になりました。
原因はわかりません。リブートしても同じ挙動かどうか、シングル
ユーザモードで起動するとどうなるか、/var/log に何か出ていないかを
確認してください。

>>4514 ロー
> ls ${DIR}*.CSV | sed 's/$DIR}//g'
'' で囲んだら変数展開されないので、"" で囲みましょう。変数展開できた
としても s//home/guest///g は sed 的にエラーですが、これはまた別の話。

> ls、変数に格納し、awk等で、「test0005.CSV」を求めたいのですが。
「ls で表示したときに最後に表示される行」とみなせるのであれば、
    echo $FileLst | awk '{print $NF}'
など ($NF は gawk では動きましたが、一般的な awk で使用できるかどうかは
わかりません)。

まぁ、awk には列で渡すのではなく、行で渡した方が幸せだと思うので、
    ls /tmp/*.CSV | awk 'END { print }'
の方がいいと思います。とか言い出すと、
    ls /tmp/*.CSV | tail -1
でいいじゃん、って話になりますけどね。

No. 4517 # ロー 2006/02/13 (月) 13:22:09
>>4516 68user

ありがとうございます。
>> ls ${DIR}*.CSV | sed 's/$DIR}//g'
>'' で囲んだら変数展開されないので、"" で囲みましょう。変数展開できた
>としても s//home/guest///g は sed 的にエラーですが、これはまた別の話。
ダブル「""」で囲んだら展開されませんでした。シングル「''」で囲んだら展開
されました。

> echo $FileLst | awk '{print $NF}'
>など ($NF は gawk では動きましたが、一般的な awk で使用できるかどうかは
>わかりません)。
一般的なawkでも使用できました。

>ls /tmp/*.CSV | awk 'END { print }'
は、ダメでした
結果が得られませんでした。

No. 4518 # zsh 2006/02/15 (水) 11:38:18
>>4512
FNR に現在処理しているファイルのカレントレコード番号が
セットされるのに対して、NR には (n)awk が実行されてから
読み込んだレコード数がセットされています。
  $ nawk '{ print "NR:" NR "/FNR:" FNR }' a.txt b.txt
等とすれば違いが確認できると思います。

>>4517 ロー
Solarisの(n)awkでは
  $ /tmp/*.CSV | awk '{ f=$0; } END { print f }'
のようにしないといけないようです。

No. 4519 # 2006/02/15 (水) 17:14:16
>>4518 zsh
ありがとうございます。

awkのmatch関数なのですが、awk内で使用するとエラーが
ですのですが、どこか使い方がいけないのでしょうか。

抜粋ですが、
awk '
{
pos=match($1,/.CSV$/);
}' ${TEMPFILE}
ファイル名から拡張子以降を取り除くため、拡張子までの
位置を求めようとしています。

awk: syntax error near line 10
awk: illegal statement near line 10
awk: 構文エラー (10 行目の周辺)
awk: 不正な文を検出しました。 (10 行目の周辺)
が発生します。

No. 4520 # zsh 2006/02/15 (水) 19:21:20
>>4519
Solaris 標準の awk (/usr/bin/awk) には、match 関数が存在しません。
対応策としては
  (1)index 関数を使用する
        →ただし、index 関数は正規表現を使用できません。
  (2)nawk を使用する
  (3)/usr/xpg4/bin/awk を使用する
といった所でしょうか。

No. 4521 # dynamite 2006/02/16 (木) 02:31:45
>>4516 68user
返答ありがとうございます。

マニュアルは下記をざっと目を通してみたのですが、記載が見付けれませんでした。
http://www.infoscience.co.jp/technical/openssl/news/
http://home.att.ne.jp/theta/diatom/

前回の書き込みで受信関係がおかしいと推測してしまいましたが、
ためしにContent-Lengthの値分だけ受信しても同じ状態なので、
現在、違う部分も検証しています。

また理解が深まりましたら報告させて頂きますm(_ _)m

No. 4522 # むう 2006/02/16 (木) 17:30:44
はじめまして。素朴な疑問があるので、もし知っておられたらお答えください。
一般論として、ネットワーク上ではTCPとUDPはどっちが優先度が高いのでしょうか?
輻輳した場合に生き残る確率?に違いはありますか?
とにかくガンガンパケットを送りつけるプログラムで実験してみたところ、
気持ち程度UDPが優先されている気がしますが、確証が持てません。
LinuxのsocketオプションにSO_PRIORITYというのがあり、デフォルトは
TCPもUDPも0でした。
setsockoptで優先度を変えてみても誤差程度の差しか認識できません。
Webで「TCP UDP 優先度」などで探してもいい資料が見つからない状態です。
何かそのあたりの情報を知っていたら教えていただけないでしょうか。

No. 4523 # 68user 2006/02/17 (金) 00:52:11
>>4522 むう
- 一般的に、OS がどちらを優先するということは聞いたことがない。
- ただ、実装によっては得手不得手がある可能性はある。
- しかし一般的に TCP の方が高機能であり行うべき処理も多いため、
    スループットという点に関しては UDP の方が有利であろう。
- 当然ながら帯域制御ができるルータ・OS であれば、どちらかを優先する
    ことは可能であろうが、これは設定の問題。
- SO_PRIORITY は IP の TOS (Type of Service) に設定される。
- TOS の値を改変してしまうルータがあるようで、チェックサム計算からは
    除外されたりするかわいそうなフィールド。
- また、TOS は DiffServ など全く別の用途に使われたりもする。
        http://x68000.q-e-d.net/~68user/rfc/?key=2474&target=title
- OS が TOS を参照するかどうかは怪しいのでは? (ルータならともかく)
- TOS で QoS をやりたいならイントラ内で使うこと。ルータは TOS 対応の
    ものを揃えるべき。
- 少なくともインターネット経由では、ピアまで TOS がそのまま流れる
    保障は全くない。
- Arcstar のように、TOS を考慮するとうたっているサービスはある。
        http://www.ntt-vpn.com/ip-vpn/faq/faq_02.html

というのがわたしの認識です。

No. 4524 # かつや 2006/02/19 (日) 15:19:55
Wic-PC上で起動した際Teratermウィンドウがタスク上に隠れて
しまいタスクトレイ上にある該当画面を選択しなければ画面上
に表示されません。設定で画面がフォアに表示されるように
する為の設定方法をご教示下さい。

No. 4525 # 68user 2006/02/19 (日) 23:35:20
>>4524 かつや
http://search.vector.co.jp/search?query=%8D%C5%91O%96%CA などのツールを
インストールするのがよいのではないでしょうか。

No. 4526 # mkt 2006/02/20 (月) 04:05:17
>>4516 68user
いろいろありがとうございます。お手数をおかけしました。

> " の解決のため、10年近くつぎはぎでやってきた汚い部分を全面的に見直し
> たため、もしかしたら UNIX の部屋の検索部分にエンバグしている可能性が
> あります。怪しい挙動を見つけられた方は教えていただけると幸いです。

自分 1 人暴走している感じで恐縮ですが、いろいろ試してしまいました。

全角記号を検索したときの挙動について。
- 半角に変換して検索されている*ものもある*。
    (「@」「〜」「:」などは半角に変換されている)
- ヒットしなかったときのキーワードの表示が文字化けしている。(*1)
    (「!」「;」「¥」など多数)
- 関係ない結果が表示される。(*2)
    (「”」「’」「|」など)

半角記号で全文検索したときの挙動について。
- 「ある」はずなのに「ヒットしませんでした。」と言われる。
    (「"」→ \&quot\; がないと言われる、「'」→ \&apos\; がないと言われる、など)
- ヒット数表示の次の、リストの先頭に空の項目が入って、
    unix-term-dic.html や pregmemo.html などの各検索対象ファイルから
    関係ない部分(検索キーワードによって範囲は異なるが google_ad 関連スクリプトの
    <!-- の後から 先頭項目のあたり?)まで拾ってきてしまっている。
    (「!」「=」「:」「@(=@)」「*」など多数)

あと、「+」を検索しようとすると「500 Internal Server Error」に
なりますね。何も入力しなかった場合とかもですが。

---
(*1)(*2)
記号ばかり試していましたが、普通に言葉を検索しても何か変です。
「あいうえお」→ 1 件ヒットしました。(これは実際存在したので問題ない)
「かきくけこ」→ ヒットしませんでした。(が、キーワード文字化け)
「鶴」→ ヒットしませんでした。(が、キーワード文字化け)
「亀」→ 3 件ヒットしました。(が、どれも関係ないものばかり)
という感じで。


…もっとスマートに分類できたらいいんですが、収拾つかなくなってしまいました。
ごちゃごちゃに突っつくだけ突っついて申し訳ありません。

No. 4527 # mkt 2006/02/20 (月) 04:16:22
>>4526 mkt
言わずもがなですが、
    pregmemo.html は prgmemo.html の typo
です。失礼しました。

No. 4528 # 68user 2006/02/21 (火) 02:26:55
>>4526 mkt
ずいぶんヌルい修正をしてしまい、お恥ずかしい限りです、

> - ヒットしなかったときのキーワードの表示が文字化けしている。(*1)
> (「!」「;」「¥」など多数)
正規表現で検索しているため、入力された文字列は quotemeta している
のですが、quotemeta すると EUC-JP の 0x80 以降も quote されてしまい、
その結果化けていました。これまでは quotemeta した後に
    s/\\([\x80-\xff])/$1/g;
で元に戻していたのですが、前回の修正時になぜか戻す必要はないと判断
して、上記の s/// を削除していました。

> - 関係ない結果が表示される。(*2)
> (「”」「’」「|」など)
全角->半角変換が甘くて、" ' | などはそもそも半角に置換していません。
調査していないので想像ですが、EUC-JP の 2バイト目 + 後続バイトに
マッチしてしまったのではないかと思います。

> <!-- の後から 先頭項目のあたり?)まで拾ってきてしまっている。
> (「!」「=」「:」「@(=@)」「*」など多数)
全文検索のテストが甘かったようです。

> あと、「+」を検索しようとすると「500 Internal Server Error」に
> なりますね。何も入力しなかった場合とかもですが。
空の場合は
    print "検索内容を指定してください。\n";
と表示するようにしていたのですが、前回の修正で Content-type ヘッダの
出力方法を変更したせいで、Content-type より前に
    検索内容を指定してください。
が出力され、エラーとなっているようです。

少しずつ直していきます。ご指摘ありがとうございました。

No. 4529 # hoge 2006/02/21 (火) 12:44:56
>>4524 かつや
Tera Term のショートカットのプロパティ中の
『実行時の大きさ』って項目はどうなっていますか?

No. 4530 # でたち 2006/02/27 (月) 02:12:36
Cシェルでシェル変数に代入された数値として
例えば0.12が入っている場合、その変数の数値を$で
参照する時に「0.12」としてではなく、
「.12」と出力させることはできますか?
ご教示頂けましたら幸いです。

No. 4531 # 68user 2006/02/27 (月) 12:00:12
>>4530 でたち
printf(1) で何とかならないかと思って試してみましたが、どうやら無理っぽいので
    echo ${var:s/0././}
でどうでしょうか。

No. 4532 # でたち 2006/02/27 (月) 18:15:08
>>4531 68user
echo ${var:s/0././}
を行ってみましたが Variable syntax表示で
受け付けて貰えませんでした。
ご返信頂きまして大変ありがとうございます。

No. 4540 # べた 2006/03/17 (金) 18:50:45
nawkの使い方について教えて欲しいことがあります。
環境は、Solaris8、shです。

nawk '{
  :
    FNO=sprintf("%d",substr(FNM,19));
  :
}' ${LIT}

上記のように、ファイル名からファイルの番号を
取得し、格納しています。
"%d"を指定して数値で取得しようとしているのですが
10以上がとれません。
9のまななのですが、どこがいけないのでしょうか。

No. 4541 # 68user 2006/03/18 (土) 23:41:25
最近掲示板 SPAM がひどいので、特定文字列を含む投稿を禁止するように
しました。

>>4540 べた
FNM の内容がわからないと何とも言えないです。

No. 4542 # 68user 2006/03/18 (土) 23:55:07
>>4088 tansy
>>4191 無題
>>4225 mmm
いまさらですが、当ページのプログラムのライセンスは、特に記述がない限り、
修正 BSD ライセンスっぽいものであることを明記しました。
    http://X68000.q-e-d.net/~68user/link.html

No. 4543 # 68user 2006/03/19 (日) 05:00:13
>>4526 mkt
一部のみですが対応しました。
    http://x68000.q-e-d.net/~68user/cgi-bin/cvsweb.cgi/public_html/unix/script/pickup#rev1.24

残件は、
    - 全文検索がダメダメなのを直す
    - EUC-JP のバイトの境界を正しく見る
        (「亀」は「正規表現」の「正」の 2バイト目と「規」の 1バイト目にマッチしている)
    - 「+」が検索できないのを直す
です。忘れないよう
    http://x68000.q-e-d.net/~68user/bugnote/viewbug.php?projectid=1&bugid=23
に登録済ですが、もしさらなる不具合があれば掲示板にてお教えいただけると幸いです。

No. 4544 # 68user 2006/03/22 (水) 01:41:10
UNIX の部屋で、各 OS のマニュアルへのリンクを表示するようにしました (先頭部分)。
    http://X68000.q-e-d.net/~68user/unix/pickup?find

現時点では、Linux・NetBSD・FreeBSD・HP-UX11i・Solaris10 のセクション 1,1M,8
のみです。

No. 4550 # タバスコ=ダ=ガマ 2006/03/25 (土) 14:57:56
ネットワークプログラミングのページはとてもお勉強になります。
非常にありがたく利用させていただきました。感謝です。
ところで素朴な疑問なのですが、TCPでsocket生成→connectの間に
bindが不要なのはなぜなのでしょう?

No. 4551 # だだ 2006/03/29 (水) 02:01:19
Solarisで、Perlを組むのですが、参考になる本を
教えてください。
Perlの基本となることが知りたいのです。
変数の設定、判定、ループ、読み書きといったことです。
基本的なことが分かる本を教えてください。

最終的には、Perlでftpやメール送信(smtpでの)を
やりたいのです。
この点に関する本も教えて欲しいのですが。

No. 4552 # 68user 2006/03/29 (水) 10:57:54
>>4550 タバスコ=ダ=ガマ
bind(2) することはできますが、普通はしません。connect(2) に
空いているポート番号を選ばせます。
    http://www.kt.rim.or.jp/~ksk/sock-faq/unix-socket-faq-ja-3.html#ss3.6

その理由は、ピアのポート番号選択は
    - 21 なら SMTP
    - 80 なら HTTP
などとサービスの選択も兼ねていますが、ローカルのポート番号は
何番でも構わないからです。

>>4551 だだ
> Perlの基本となることが知りたいのです。
> 変数の設定、判定、ループ、読み書きといったことです。
> 基本的なことが分かる本を教えてください。
初心者向けの本は相性が重要ですので、本屋で手にとって立ち読みするのが
よいでしょう。本屋に行くことができないなら、わたしは持っていませんが
「初めての Perl」を推薦します。

> 最終的には、Perlでftpやメール送信(smtpでの)をやりたいのです。
「Perl クックブック Volume1・2」で最終的な答えを把握した上で、
「プログラミング Perl」で基礎を固めるのがよいと思います。

No. 4554 # かず 2006/03/29 (水) 13:08:48
いつも楽しんでサイトを拝見させていただいております。

今UNIX上でクライアント、サーバのネットワークプログラミングをC言語で
挑戦しているところなんですが、FTPコマンド
(QUIT,USER,PASS,PWD,STAT,MKD,RMD,CDW,DEL,LIST,HELPcmd,HELP,PORT,NLST)
の組み込み方がイマイチよく分りません。

以下にserverftp.cとclientftp.cのコードを貼り付けておきます。
これらのコードは正常に動いております。

大変お忙しいとは思いますが、
ご教授の程、どうぞよろしくお願い致します。

serverftp.c

***********************

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>

#define SERVER_FTP_PORT 9237

// list function prototypes
int receiveMsg(int s, char *buf, short bufsize, short *msgsize);
int sendMessage(int s, char *buf, short size);

main(
int  argc,
char *argv[]
)
{
int listenSocket;
int s;
int status;
                short msgSize;

printf("Starting server ftp\n");

status = svcInitServer(&listenSocket);
if(status != 0)
{
printf("Exiting server ftp due to error\n");
exit(-1);
}

for(;;)
{
printf("waiting to accept client connection\n");
s = accept(listenSocket, NULL, NULL);
if(s < 0)
{
perror("cannot accept connection: ");
exit(-1);
}

int msg;
short size;
char recvBuffer[1024];

printf("Server connected to client, issuing recvmsg\n");

status = receiveMsg (s, recvBuffer, 1024, &msgSize);
if (status < 0)
{
close(s);
return(status);
}

char replyMsg[1024];
strcpy(replyMsg, "200 command ok\n");
size = strlen (replyMsg) + 1;
status = sendMessage(s, replyMsg, size);

if(status < 0)
{
close(s);
return(s);
}



}

close(listenSocket);
printf("Exiting from server ftp main\n");
}


int svcInitServer(
int *s
)
{
int sock;
struct sockaddr_in svcAddr;
int qlen;

if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("cannot create socket ");
return(-1);
}

memset((char *) &svcAddr, 0, sizeof(svcAddr));

svcAddr.sin_family = AF_INET;
svcAddr.sin_addr.s_addr = htonl(INADDR_ANY);
svcAddr.sin_port = htons(SERVER_FTP_PORT);

if(bind(sock,(struct sockaddr *)&svcAddr, sizeof(svcAddr)) < 0)
{
perror("cannot bind ");
close(sock);
return(-1);
}

qlen = 1;
listen(sock, qlen);

*s = sock;

return(0);
}


int sendMessage(
int s,
char *msg,
short msgSize
)

{

int i;

for(i = 0; i < msgSize; i++)
{
printf("%c", msg[i]);
}
printf(" \n");




if((send(s, msg, msgSize, 0)) < 0)
{
perror("unable to send ");
return(-1);
}

return(0);
}


int receiveMsg(
int s,
char *buffer,
short bufferSize,
short *msgSize
)

{
int i;
*msgSize = recv(s, buffer, bufferSize, 0);
if(*msgSize < 0)
{
perror("unable to receive");
return(-1);
}

for(i = 0; i < *msgSize; i++)
{
printf("%c", buffer[i]);
}
printf("\n");

return(0);
}


clientftp.c

**********************

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>

#define SERVER_FTP_PORT 9237

int sendMessage(int s, char *msg, short msgSize);
int receiveMsg(int s, char *buffer, short bufferSize, short *msgSize);


int main(
int argc,
char *argv[]
)

{
int status;
int s;
short msgSize;
char FTPcmd[1024];
char replyMsg[1024];

printf("Trying to connect to server FTP\n");

status = clntConnect("//IPアドレス", &s);
if(status < 0)
{
return(status);
}

printf("Connected to ftp server\n");
strcpy(FTPcmd, "quit");
status = sendMessage(s, FTPcmd, strlen(FTPcmd) + 1);
if(status < 0)
{
close(s);
return(s);
}

printf("Issuing receivemsg to get reply msg from server\n");
status = receiveMsg(s, replyMsg, 1024, &msgSize);
if(status < 0)
{
close(s);
return(s);
}

printf("%c", replyMsg);

close(s);
return(0);

}

int sendMessage(int s, char *msg, short msgSize)

{
int i;

for(i = 0; i < msgSize; i++)
{
printf("%c", msg[i]);
}

printf(" \n");



if((send(s, msg, msgSize, 0)) < 0)
{
perror("unable to send ");
return(-1);
}

return(0);
}

int receiveMsg(int s, char *buffer, short bufferSize, short *msgSize)

{
int i;
*msgSize = recv(s, buffer, bufferSize, 0);
if(*msgSize < 0)
{
perror("unable to receive ");
return(-1);
}

for(i = 0; i < *msgSize; i++)
{
printf("%c", buffer[i]);
}

printf("\n");
return(0);

}

int clntConnect(
char *serverName,
int *s
)

{
int sock;
struct sockaddr_in us;
struct sockaddr_in them;
struct hostent *he;

if((he = gethostbyname(serverName)) == NULL)
{
printf("%s is unknown server\n", serverName);
return(-1);
}


if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("cannot create socket ");
return(-1);
}


memset((char *) &us, 0, sizeof(us));

us.sin_family = AF_INET;
us.sin_addr.s_addr = htonl(INADDR_ANY);
us.sin_port = 0;

if(bind(sock,(struct sockaddr *)&us, sizeof(us)) < 0)
{
perror("cannot bind");
close(sock);
return(-1);
}


memset((char *)&them, 0, sizeof(them));
them.sin_family = AF_INET;
memcpy((char *) &them.sin_addr, he->h_addr, he->h_length);
them.sin_port = htons(SERVER_FTP_PORT);

if(connect(sock,(struct sockaddr *)&them, sizeof(them)) < 0)
{
perror("cannot connect ");
close(sock);
return(-1);
}

printf("Connected to server, socket number: %d\n", sock);
*s = sock;

return(0);
}

void clntExtractReplyCode(
char *buffer,
int *replyCode
)

{
sscanf(buffer, "%d", replyCode);

return;
}

No. 4555 # hoge 2006/03/29 (水) 19:29:01
>>4554 かず さんへ

> FTPコマンド
> (QUIT,USER,PASS,PWD,STAT,MKD,RMD,CDW,DEL,LIST,HELPcmd,HELP,PORT,NLST)
> の組み込み方がイマイチよく分りません。

あんまりな方法だと思いますよ。
vsftpd とか proftpd 辺りのソースを拾って読んでみてはどうでしょうか?

No. 4556 # まんたろう 2006/03/30 (木) 01:10:57
Solarisで、Perlで、smtpで、メール送信をしていいます。
ポート番号25を使って、smtpサーバに接続してメールの
送信をしているのですが、処理は、正常に終わるのですが、
メールが送信されません。届きません。
どこがいけないのでしょうか。

------------------------------
use Socket;
$server = 'SMTPサーバ' ;

$from = '送信元アドレス' ;
$to = '送信先アドレス' ;
$subject = 'テストメール' ;
$data = 'メール送信テスト' ;

$send_data = 'X-Mailer: SMTP tool' . "\n";
$send_data .= 'MIME-Version: 1.0' . "\n";
$send_data .= 'Content-Type: text/plain; charset=iso-2022-jp' . "\n";
$send_data .= 'From: '. $from . "\n";
$send_data .= 'To: '. $to . "\n";
$send_data .= 'Subject: ' . $subject . "\n";
$send_data .= "\n";
$send_data .= $data;

        $port = getservbyname('smtp','tcp');
        $struct = sockaddr_in($port,inet_aton($server));
        socket(SH, PF_INET, SOCK_STREAM, 0)
                                || die("ソケットの生成失敗 $!") ;

        connect(SH, $struct )
                                || die("接続失敗 $!") ;

        select(SH); $| = 1; select(STDOUT);

        $respons = <SH> ;

        unless($respons =~ /^220/) {
                close(SH); die("接続失敗 $!") ;
        }

        $command = "HELO $server\n";
        print SH $command ;

        $respons = <SH> ;
        &decode(\$respons) ;

        unless($respons =~ /^250/){
                close(SH); die("HELOコマンド失敗 $!") ;
        }

        $command = "MAIL FROM:$from\n";
        print SH $command ;

        $respons = <SH> ;
        &decode(\$respons) ;

        unless($respons =~ /^250/){
                print SH "RSET\n"; close(SH);
                die("MAILコマンド失敗 $!") ;
        }

        $command = "RCPT TO:$to\n";
        print SH $command ;

        $respons = <SH> ;
        &decode(\$respons) ;

        unless($respons =~ /^25[0|1]/){
                print SH "RSET\n"; close(SH);
                die("RCPTコマンド失敗 $!") ;
        }

        $command = "DATA\n";
        print SH $command ;

        $respons = <SH> ;
        &decode(\$respons) ;

        unless($respons =~ /^354/){
                print SH "RSET\n"; close(SH);
                die("DATAコマンド失敗 $!") ;
        }

        $command = "$send_data\n.\n";
        print SH $command ;

        $respons = <SH> ;
        &decode(\$respons) ;

        unless($respons =~ /^250/){
                print SH "RSET\n"; close(SH);
                die("本文、ヘッダ部送信失敗 $!") ;
        }

        $command = "QUIT\n";
        print SH $command ;

        close(SH); select(STDOUT);
        
        print "MAILは正常に送信されました。\n";

sub decode{
        
        my $inf = $_[0];
        $$inf =~ s/\x0D\x0A|\x0D|\x0A/\n/g;

}
-----------------------------

No. 4557 # megu 2006/03/30 (木) 11:46:30
UNIXを良く知らずみようみまねでshellを作成しています。
ある処理のエラーをハンドリングして結果に対してメール
を送信する様にしました。
/usr/bin/mail -s "hoge" megu@hoge.com < hoge.txt
ここで質問なのですが、該当コマンドをプロンプト上で
実行すると処理が実行されません。
(実行中のまま戻って来ない?)
強制終了すると、dead.letterが更新されます。
該当処理を記載したshellを実行しても、上記コマンド迄
は実行されているのですが、該当mailコマンドの部分で
処理がされない様で、コマンドを実行した様にshell自体も
終了しません。
cronや他ツールで自動実行させる様にすると実行されます。
根本的なOSの知識なのか、環境の問題なのかさえも分かりません。
とても基本的な質問になるかと思うのですが、教えて頂ければと
思います。

No. 4558 # カルネ 2006/03/30 (木) 19:43:41
はじめまして。質問させてください。
sin_port=0で空いているポート番号を自動取得できますが、
・ここで取得されたくない番号を指定
・決められた帯域内(5000〜6000など)で限定して取得
・予め取得される範囲を取得
のいずれかを行いたいのですが、方法はありますでしょうか?

No. 4559 # 68user 2006/03/30 (木) 22:25:05
>>4556 まんたろう
> ポート番号25を使って、smtpサーバに接続してメールの
> 送信をしているのですが、処理は、正常に終わるのですが、
> メールが送信されません。届きません。
うちの環境では正常に送信されました。telnet での送信や、メーラー
送信のパケット観察などを行って、成功/失敗時の違いを観察してください。

>>4557 megu
- 「sh -x スクリプト名」として、実際に実行されているコマンドを確認する。
    端末からの入力を待っているなら、リダイレクトまわりが怪しげな気が。
- dead.letter の中を見て、エラーを観察する (dead.letter の中にエラーが
    記述されるのかは覚えていませんが)
- mail コマンドが吐くエラーを観察する。標準出力・標準エラー出力を捨てて
    いるなら、捨てないようにする。

>>4558 カルネ
Linux なら ip_local_port_range、NetBSD なら net.inet.ip.anonportmax、
FreeBSD なら制限方法がない (たぶん) など、OS によって異なります。

No. 4560 # べた 2006/04/06 (木) 13:07:50
シェルで、dateコマンドで取得した時間から5分前の
の時間を取得したいのですが、できるでしょうか。

date +%H%M%S と実行します。
結果として、「130530」が取得できます。
そこから、取得した、「1305030」から5分前の「130030」を
求めたいのですが、できるのでしょうか。

環境は、
Solaris、shです。

No. 4561 # 68user 2006/04/06 (木) 14:09:14
>>4560 べた
上にある方が、現実的な解です。

- perl で localtime(time-5*60)
- GNU date をインストールして date --date '5 minutes ago'
- http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=1382 的なやり方
- http://home.catv.ne.jp/pp/ginoue/bn/descend.html の「2002/04/02 ひとこと」
    的なやり方

No. 4562 # hoge 2006/04/06 (木) 16:23:10
プロパーや一次請けが perl を嫌がったり、ましてや非純正な物
(GNU プロダクト)を入れるなんて駄目なんて悲惨な職場を経験したので...

Solaris 付属の date コマンドに %T って有りますか?
無かったとしても date +%H:%M:%S って書き方は利用可能ですか?
結果として、13:05:30 が取得できるなら、予め IFS_OLD=$IFS ; IFS=":" して
2 番目のフィールドが 5 未満か? とか 1 番目のフィールドが 0 以下か? って
辺りを条件に繰り下がり処理を手作りするのもありますね。

No. 4563 # hoge 2006/04/06 (木) 17:48:41
あ... 68user さんが例示してるやん。
リンクは読んでから書かないと駄目ね。

No. 4564 # べた 2006/04/06 (木) 18:37:37
>>4561 68user
>>4562 hoge
ありがとうございます。
日付またがりなどを考えるとPerlでやる方法がいいです。
Perlでやります。

もう1つ質問があります。
シェルを起動し、起動した時間から5分前に出力された時間以降の
syslogの内容を別ファイルに出力したいのですが、できるのでしょうか。

例えば、
今が、18:00:00とします。
シェルを起動し、18:00:00を取得します。
18:00:00を基にして、5分前の17:55:00を取得します。
「Apr 6 18:55:00」以降に出力されたsyslogをすべて
別ファイルに出力します。

ということ実現したいのです。

時間は、
$tm = time - 300;
my $now = strftime "%b %e %H:%M:%S", localtime($tm);
で取得します。

No. 4566 # べた 2006/04/08 (土) 12:36:36
あるファイルから指定日時以降に書かれたレコードを
抽出したいのですが、シェルスクリプトでできるので
しょうか。
どのしょうにシェルにすればよいか教えてください。

例えば、今が、2006/04/08 12:30:00とします。
ある指定日時というのは、現時点から5分前としますので、
2006/04/08 12:25:00となります。

ファイルでは、「Apr 8 12:30:33 ・・・・・」と出力
されているので、5分まえの時間を、「Apr 8 12:25:00」
で取得し、「Apr 8 12:25:00」以降に書かれたレコードを
ファイルに出力したいのです。

環境は、
Solaris8、sh、Perlで実現したいのです。

No. 4567 # まんたろう 2006/04/10 (月) 21:07:44
>>4566 べた

無理ではないかと思うのですが。
「Apr 8 12:30:33 ・・・・・」の比較、チェックが簡単
にできないと思います。

こういうのはどうですか。
5分前に動いた時のファイルのレコード数と今回動いた時の
ファイルにレコード数の差をtailコマンドでファイルに出力
というのは。?

No. 4568 # 68user 2006/04/11 (火) 10:22:32
>>4567 まんたろう
> 「Apr 8 12:30:33 ・・・・・」の比較、チェックが簡単にできないと思います。
echo "Apr 02 12:25:00 ===" | sort -M - logfile | cat -n | grep "===" | awk '{print $1}'
として行番号をとって、その行以降を tail で出力とか。

まぁ筋の悪いやり方だとは思いますので、他の方法がよいでしょう。

No. 4569 # べた 2006/04/11 (火) 12:50:22
>>4568 68user

>echo "Apr 02 12:25:00 ===" | sort -M - logfile | cat -n | grep "===" | awk '{print $1}'
>として行番号をとって、その行以降を tail で出力とか。
予めファイルの全体のレコード数も必要ということですか。
マイナスとなった場合、どうなるのですか。?

No. 4570 # べた 2006/04/11 (火) 14:56:25
>>4578 EBA

echo "Apr 10 09:30:00 ===" | sort -M - logfile | cat -n | grep "===" | awk '{print $1}'
と実行してみたのですが、行番号が2となります。

# cat logfile
<pre>
Apr 9 12:23:01 ・・・・・・・
Apr 9 15:17:43 ・・・・・・・
Apr 9 17:48:06 ・・・・・・・
Apr 9 18:05:30 ・・・・・・・
Apr 9 18:06:24 ・・・・・・・
Apr 10 09:23:08 ・・・・・・・
Apr 10 11:47:23 ・・・・・・・
Apr 10 13:35:49 ・・・・・・・
Apr 11 09:54:11 ・・・・・・・
Apr 11 12:17:38 ・・・・・・・
</pre>

行番号ではなく、すべてを表示したのですが、
sortが正しく行われていないみたいなのですが、
どうしてなのでしょうか。
<pre>
# echo "Apr 10 09:30:00 ===" | sort -M - logfile | cat -n
          1 Apr 9 12:23:01 ・・・・・・・
          2 Apr 10 09:30:00 ===
          3 Apr 9 15:17:43 ・・・・・・・
          4 Apr 9 17:48:06 ・・・・・・・
          5 Apr 9 18:05:30 ・・・・・・・
          6 Apr 9 18:06:24 ・・・・・・・
          7 Apr 10 09:23:08 ・・・・・・・
          8 Apr 10 11:47:23 ・・・・・・・
          9 Apr 10 13:35:49 ・・・・・・・
        10 Apr 11 09:54:11 ・・・・・・・
        11 Apr 11 12:17:38 ・・・・・・・
</pre>

行番号以降をtailで出力は、
# tail +行番号 logfile
でできました。

赤色の文字は 「Windows 機種依存文字」か、いわゆる「半角カナ」です。 この掲示板では自動変換されますが、今後は使用しないで下さい

No. 4571 # 68user 2006/04/12 (水) 11:30:06
>>4570 べた
Linux ではうまくいきましたが、Solaris 環境がないので確認できません。
どなたかご確認いただけませんか?

あと、このやり方は新年 00:00:00〜00:05:00 の間はうまく動作しませんので、
おすすめしません。念のため。

No. 4572 # べた 2006/04/12 (水) 17:05:17
>>4571 68user
ありがとうございます。

>あと、このやり方は新年 00:00:00〜00:05:00 の間はうまく動作しませんので、
>おすすめしません。念のため。
確認して頂いたのですか。
良い方法だと思ってはいたのですが、ダメですか。
他に、良い方法があるのでしたら伺いたいのですが。

No. 4573 # ふくし 2006/04/12 (水) 21:16:07
おひさしぶりです。自分が困ったときだけ出てきてすみません。

Windows のマシンと UNIX のマシンが存在する LAN で、
お互いにメールを送りあうというテストをやっています。
ここでは簡単のため、Windows マシン1台と UNIX マシン1台とします。

W に pmail というフリーウェアの SMTP / POP サーバーを入れた人がいて、
W と U の両方に Mozilla Thunderbird を入れて、
Thunderbird のアカウント設定で、
W の IP アドレスを SMTP / POP アドレス欄に指定することで、
W と U の間でメールのやり取りをすることができました。

しかし、テストの要件のひとつに、
U 側では MUA として /bin/mail も使えるようにする、というものがありました。
sendmail の設定を変えようとしようと思ったのですが、
それは大変だからやめたほうがいいと上司に言われ、
言われるままに U に Postfix を入れました。
ちなみに U の OS は HP-UX 11i ver.2 です。

Postfix のインストールはなんとなく終わりました。
/etc/postfix/main.cf に
myhostaname = U.unix.net
と変更を加えました。

DNS を立てるのはなかなか面倒だと上司に言われたので、言われるままに
U の /etc/hosts および
W の C:\Winnt\system32\drivers\etc\hosts に
172.16.10.2 U.unix.net
172.16.10.3 W.windows.net
のように書きました。

で、U 側で
  # mail root
  nantoka
  kantoka
  .
のように書くと、
  # mail
で自分宛に出したメールが確認できましたが、
  # mail dareka@W.windows.net
  nandakakandaka
  .
のようにすると、
  Diagnostic-Code: X-Postfix; Host or domain name not found. Name Service
    error for name=W.windows.net type=A: Host not found
のように怒られます。

(ここで、dareka は W の pmail に設定したメールアカウントです。)

U から
  # nslookup
  > W.windows.net

とすると 172.16.10.3 が、

  > 172.16.10.3

とすると W.windows.net が正しく帰るのですが、
host W.windows.net とすると not found 3(NXDOMAIN) と言われます。
このへんが原因でしょうか。

この状況で、U から W に /bin/mail でメールを出すことができるでしょうか。

また、W の Thunderbird から出したメールを
U の /bin/mail で受けるためには、qpopper のようなプログラムを
U に入れないといけないのでしょうか。

他に、いまの私の状況でもっと簡単にテストするアイディアがわかれば
ご教示ください。

いろいろ聞いてすみません。よろしくお願いします。

No. 4574 # 68user 2006/04/13 (木) 01:31:52
>>4572 べた
> 他に、良い方法があるのでしたら伺いたいのですが。
まず、syslog の出力には年がないという根本的欠陥があります。なので、
ログファイルを後からチェックするだけでは、完璧な判定はできません。
たとえば
    Apr 9 12:23:00 ... (2005年出力)
    Apr 9 12:23:01 ... (2006年出力)
とか
    Apr 9 12:23:01 ... (2005年出力)
    Apr 9 12:23:00 ... (2006年出力)
というケースもありうるわけです。また、現在 1月1日 0時2分だとして、
1分前に出力されたログ
    Jan 1 00:01:00 ...
と、5分前の時刻
    Dec 31 12:57:00 ...
をソートすると Jan 1 の方が先になり、意図した結果になりません。

それを踏まえた上で、
    - 1年前のログが残っていることはないとみなす
    - 年初 5分は目をつぶる
が許容できるかどうかはあなたが判断してください。なお、Jan や Feb の
ソートについては、sed で 01 や 02 に置換すれば何とでもできるでしょう。

理想は年が記録されるログに乗り換えることですが (=syslog を捨てる)、
それが許されるシチュエーションはあまりないと思いますので、
>>4567 まんたろう
は現実的な落としどころと考えます。


>>4573 ふくし
> Diagnostic-Code: X-Postfix; Host or domain name not found. Name Service
> error for name=W.windows.net type=A: Host not found
Postfix はよく知りませんが、
    http://www.kobitosan.net/postfix/ML/arc.4/msg00048.html
でしょうか。あと、うまくいくかどうかわかりませんが、
    # mail 'dareka@[172.16.10.3]'
と IP アドレスを直接指定するとか。@[..] は IP アドレス指定の場合の
メールアドレス記述方法だったような気がしますが、使ったことはありません。

# http://x68000.q-e-d.net/~68user/rfc/?key=821&target=title

> # nslookup
nslookup は、/etc/hosts を参照しません。

と思ったら、HP-UX の nslookup は参照するんですね。へぇ。
    http://docs.hp.com/ja/B2355-90851/nslookup.1.html

> また、W の Thunderbird から出したメールを
> U の /bin/mail で受けるためには、qpopper のようなプログラムを
> U に入れないといけないのでしょうか。
mail コマンドには POP クライアントの機能はないと思いますので、
W で POP サーバを動かすという前提であれば、
    - W にメールが届くと U に転送し、mail コマンドは /var/spool/mail などを
        直接参照する。
    - U で fetchmail などの POP クライアントを動かし、/var/spool/mail などに
        書き出す。
    - W・U 両方で POP サーバを動かし、W 宛のメールは W の POP サーバから
        取得し、U 宛のメールは U の POP サーバから取得する。
などの方法があります (他にもあると思いますが)。

言うまでもありませんが、要件自体が不適切である可能性もあります。

No. 4575 # ふくし 2006/04/13 (木) 14:35:00
>>4574 さん、ありがとうございます。
  # mail 'dareka@[172.16.10.3]'
を指定すると、

  Diagnostic-Code; X-Postfix; host 172.16.10.3[172.16.10.3] said: 550 5.1.1
  <dareka@[172.16.10.3]>... Not local user, server is not relaid.
  Recipient error (in reply to RCPT TO command)

と言われます。

試みに dareka というコンピューターユーザーを W に作ってみましたが
現象は変わりませんでした ;;;

教えていただいたリンクをたどって
http://www.kobitosan.net/postfix/jhtml/faq.html#intranet
に到達していくつかのことをやってみました。

・/etc/postfix/main.cf で
    disable_dns_lookups = yes と書けば
    /etc/hosts を見に行って W.windows.net の名前解決をしてくれる?
    =>ダメでした(dareka@W.windows.net で host not found になる)

・さらに /etc/postfix/main.cf で
    relayhost = W.windows.net と書く

    =>同じ状況です。
    (# mail dareka@W.windows.net で host not found、
        # mail 'dareka[@172.10.16.3]' で not a local user)

・/etc/postfix/main.cf で
    relayhost = W.windows.net と書く

    =>同じ状況です。
    (# mail dareka@W.windows.net で host not found、
        # mail 'dareka[@172.10.16.3]' で not a local user)
        これ、W.windows.net の smtp サーバーである pmail が
        POP before SMTP auth をやっているのが原因かも・・・。
        (フリー版の制約で切れない)

・relayhost の設定をやめ、
    transport_maps = dbm:/etc/postfix/transport と設定する。
    /etc/postfix/transport の中身を

    windows.net :[W.windows.net]
    .windows.net :[W.windows.net]

    にし、postmap /etc/postfix/transport をしてから、
    postfix reload する。
    (/etc/postfix/transport の前に hash、db、dbm などの何をつけるかは
        postmap が生成するデータベースによる。
        間違うと postfix reload で怒られる)

    =>同じ状況です。

・/etc/postfix/transport の中身を

    windows.net :[172.16.10.3]
    .windows.net :[172.16.10.3]

    とか

    windows.net smtp:[W.windows.net]
    .windows.net smtp:[W.windows.net]

    とか

    windows.net smtp:[172.16.10.3]
    .windows.net smtp:[172.16.10.3]

    とかにしてみる。

    =>同じ状況です。。。

ううーん、困った。
でも人に聞きながらやってると整理がついていいですね (^^)

No. 4577 # べた 2006/04/15 (土) 16:55:45
>>4547
ありがとうございます。
どうも、無理みたいですね。
1年。つまり、同じ年ということであるのならば、何とかできるの
でしょうが、年をまたいでしまうと無理ですね。

>Jan や Feb のソートについては、sed で 01 や 02 に置換すれば
>何とでもできるでしょう。
すみません。方法教えてください。


> >>4567 まんたろう
> は現実的な落としどころと考えます。
現実な落としどころとは。?

No. 4578 # EBA 2006/04/16 (日) 03:01:58
BCCでwindowsプログラムをコンパイルしようとすると
「外部シンボル '_main' が未解決」というのが出てしまいます。
「-WオプションをつけてコンパイルすればWindowsアプリができます」と本に
書いてあるのですが、どうすればいいのかわかりません

No. 4579 # べた 2006/04/18 (火) 23:58:32
以下の様なカンマ区切りのファイルがあります。
001,a2,a3,a4,a5,a6,a7,a8,a9,a10,,,,,,
002,a2,a3,a4,a5,a6,a7,a8,a9,a10,111:222,123:456,001:002,100:200,A01:A02,0:1
003,a2,a3,a4,a5,a6,a7,a8,a9,a10,111:222,123:,:,:,A01:A02,:

フィールドの11カラム以降からは、コロン区切りで複数設定されている場合がある
ので、複数行に分けたいのです。

以下の様に、
001,a2,a3,a4,a5,a6,a7,a8,a9,a10,,,,,,
002,a2,a3,a4,a5,a6,a7,a8,a9,a10,111,123,001,100,A01,0
002,a2,a3,a4,a5,a6,a7,a8,a9,a10,222,456,002,200,A02,1
003,a2,a3,a4,a5,a6,a7,a8,a9,a10,111,123,,,A01,
003,a2,a3,a4,a5,a6,a7,a8,a9,a10,222,,,,A02,
に編集し、ファイルに出力したいのですが、11カラム以降の処理が上手く行きません。
3通りほど、試してみたのですが、それぞれ駄目でした。
どこがいけないのかとどうすればよいのかを教えてください。

環境は、
Solaris8、Bシェル
です。

No.1 -----------------------------------------------------------------
#!/bin/sh
#

if [ $# -eq 0 ] ; then
        echo "$0 FileName"
        exit 1
fi

FILE=$1
OUT_FILE=kekka.log
rm ${OUT_FILE} > /dev/null 2>&1

nawk -v OUT=${OUT_FILE} '
function max_desc(lstadr,lst) {
      m=split(lstadr,lst,":") ;
      return m ;
}
{
      cnt=1 ;
      n=split($0,arglst,",") ;
      for(i=11;i<=n;i++) {
              m=max_desc(arglst[i],lst["${i}"]) ;
              if (m>cnt) { cnt=m ; }
      }

      no=1 ;
      for(i=1; i<=cnt; i++) {
            for(j=1; j<=n; j++) {
                  if (j==2) {
                        printf("%d,",no++) >> OUT ;
                  } else if (j==11 || j==12 || j==13 || j==14 || j==15 || j==16) {
                          printf("%s,",lst["${j}"][i]) >> OUT ;
                  } else {
                        printf("%s,",arglst[j]) >> OUT ;
                  }
            }
            printf("\n") >> OUT ;
      }
}' ${FILE}

exit 0

No.2 -----------------------------------------------------------------
#!/bin/sh
#

if [ $# -eq 0 ] ; then
        echo "$0 FileName"
        exit 1
fi

FILE=$1
OUT_FILE=kekka.log
rm ${OUT_FILE} > /dev/null 2>&1

nawk -v OUT=${OUT_FILE} '
function max_desc(lstadr,lst) {
        cnt=split(lstadr,lst,":") ;
        return cnt ;
}
{
        num=1 ;
        n=split($0,arglst,",") ;
        for(i=11;i<=n;i++) {
                ret=max_desc(arglst[i],lst[++x,y]) ;
                if (ret>num) { num=ret ; }
        }
        nf=x ;

        no=1 ;
        for(y=1; y<=num; y++) {
                for(j=1; j<=10; j++) {
                        if (j==2) {
                                printf("%d,",no++) >> OUT ;
                        } else {
                                printf("%s,",arglst[j]) >> OUT ;
                        }
                }
                for(x=1; x<=nf; x++) {
                        printf("%s,",lst[x,y]) >> OUT ;
                }
                printf("\n") >> OUT ;
        }
}' ${FILE}

exit 0

No.3 -----------------------------------------------------------------
#!/bin/sh
#

if [ $# -eq 0 ] ; then
        echo "$0 FileName"
        exit 1
fi

FILE=$1
OUT_FILE=kekka.log
rm ${OUT_FILE} > /dev/null 2>&1

nawk -v OUT=${OUT_FILE} '
function max_desc(lstadr,lst,x) {
        cnt=split(lstadr,arrlst,":") ;

        for(j=1;j<=cnt;j++) {
                lst[x,j]=arrlst[j] ;
        }
        return cnt ;
}
{
        num=1 ;
        n=split($0,arglst,",") ;
        for(i=11;i<=n;i++) {
                ret=max_desc(arglst[i],lst[++x,y],x) ;
                if (ret>num) { num=ret ; }
        }
        nf=x ;

        no=1 ;
        for(y=1; y<=num; y++) {
                for(j=1; j<=10; j++) {
                        if (j==2) {
                                printf("%d,",no++) >> OUT ;
                        } else {
                                printf("%s,",arglst[j]) >> OUT ;
                        }
                }
                for(x=1; x<=nf; x++) {
                        printf("%s,",lst[x,y]) >> OUT ;
                }
                printf("\n") >> OUT ;
        }
}' ${FILE}

exit 0

No. 4580 # zsh 2006/04/19 (水) 13:27:30
>>4579 べた
これが賢いやり方とも思えませんが、一応作ってみました。
------
$ cat a.awk
BEGIN {
        FS=",";
        chk_col=11;
} {
        if ($chk_col ~ /:/) {
                str_head=head_string();
                split_num=split($chk_col, str_foot, ":");
                for (i=1; i<=split_num; i++) {
                        for (j=chk_col+1; j<=NF; j++) {
                                split($j, col_buf, ":");
                                str_foot[i]=sprintf("%s,%s", str_foot[i], col_buf[i]);
                        }
                        print str_head "," str_foot[i];
                }
        } else {
                print;
        }
} function head_string() {
        str_buf=$1;
        for (k=2; k<chk_col; k++) {
                str_buf=sprintf("%s,%s", str_buf, $k);
        }
        return str_buf;
}
------
------
$ cat a
001,a2,a3,a4,a5,a6,a7,a8,a9,a10,,,,,,
002,a2,a3,a4,a5,a6,a7,a8,a9,a10,111:222,123:456,001:002,100:200,A01:A02,0:1
003,a2,a3,a4,a5,a6,a7,a8,a9,a10,111:222,123:,:,:,A01:A02,:
------
------
$ awk -f a.awk a
001,a2,a3,a4,a5,a6,a7,a8,a9,a10,,,,,,
002,a2,a3,a4,a5,a6,a7,a8,a9,a10,111,123,001,100,A01,0
002,a2,a3,a4,a5,a6,a7,a8,a9,a10,222,456,002,200,A02,1
003,a2,a3,a4,a5,a6,a7,a8,a9,a10,111,123,,,A01,
003,a2,a3,a4,a5,a6,a7,a8,a9,a10,222,,,,A02,
------

>>4571 68user
今更ですが、Solarisでは

$ echo "Apr 02 12:25:00 ===" | sort -M - logfile | \
    sort -n -k2,3 | cat -n | grep "===" | awk '{print $1}'

等としないとダメみたいです。

No. 4581 # べた 2006/04/19 (水) 16:30:24
>>4580 zsh
zshさん、ありがとうございます。
一応、動いたのですが、フィールド2の値を別の
文字置き換えたいのですが、どうすればよいのですか。

ファイル11以降に「:」で区切られたデータが存在した
場合、データの数分順番に番号を振りたいのです。
なければ、デフォルトで”1”としたいのです。

-----
$ cat a
001,a2,a3,a4,a5,a6,a7,a8,a9,a10,,,,,,
002,a2,a3,a4,a5,a6,a7,a8,a9,a10,111:222,123:456,001:002,100:200,A01:A02,0:1
003,a2,a3,a4,a5,a6,a7,a8,a9,a10,111:222,123:,:,:,A01:A02,:

-----
結果
001,1,a3,a4,a5,a6,a7,a8,a9,a10,,,,,,
002,1,a3,a4,a5,a6,a7,a8,a9,a10,111,123,001,100,A01,0
002,2,a3,a4,a5,a6,a7,a8,a9,a10,222,456,002,200,A02,1
003,1,a3,a4,a5,a6,a7,a8,a9,a10,111,123,,,A01,
003,2,a3,a4,a5,a6,a7,a8,a9,a10,222,,,,A02,

No. 4582 # zsh 2006/04/19 (水) 18:42:38
>>4581 べた
適当に直してみました。
------
BEGIN{
        FS=",";
        chk_col=11;
} {
        str_head_1=$1;
        if($chk_col ~ /:/) {
                str_head_2=head_string(chk_col);
                split_num=split($chk_col, str_foot, ":");
                for (i=1; i<=split_num; i++) {
                        for (j=chk_col+1; j<=NF; j++) {
                                split($j, col_buf, ":");
                                str_foot[i]=sprintf("%s,%s", str_foot[i], col_buf[i]);
                        }
                        print str_head_1 "," i "," str_head_2 "," str_foot[i];
                }
        } else {
                str_head_2=head_string(NF);
                print str_head_1 ",1," str_head_2;
        }
} function head_string(chk_point) {
        str_buf=$3;
        for (k=3; k<chk_point; k++) {
                str_buf=sprintf("%s,%s", str_buf, $k);
        }
        return str_buf;
}
------

No. 4583 # べた 2006/04/19 (水) 21:00:53
>>4582 zsh

zshさん、ありがとうございます。
>str_head_2=head_string(NF+1);
>for (k=4; k<chk_point; k++) {
の行を修正したら期待する結果が得られました。

ただ、ファイルのフォーマットに規則性がないことがわかり、
データによっては、正しく出力されないものがでてきました。
フィールド11に、「:」が存在しないデータがあるのです。

a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,111,123,SSS,A01,,:
a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,,,,123:456:789:100:100,A01:A02:A03:3A:NTT0001,

「 if($chk_col ~ /:/) {」
の判定を増やし、フィールド番号を取得できればできますか。

No. 4584 # べた 2006/04/19 (水) 22:45:43
>>4582 zsh
>>4583 べた

一応、動きます。
以下のようになるのでしょうか。

BEGIN{
        FS=",";
        chk_col=11;
}
{
        str_head_1=$1;
        split_num=chk_comma_max(NF);
        if(split_num!=0) {
                str_head_2=head_string(chk_col);
                split($chk_col, str_foot, ":");
                for (i=1; i<=split_num; i++) {
                        for (j=chk_col+1; j<=NF; j++) {
                                split($j, col_buf, ":");
                                str_foot[i]=sprintf("%s,%s", str_foot[i], col_buf[i]);
                        }
                        print str_head_1 "," i "," str_head_2 "," str_foot[i];
                }
        } else {
                str_head_2=head_string(NF+1);
                print str_head_1 ",1," str_head_2;
        }
}
function chk_comma_max(chk_point) {
        comma_num=0;
        for (k=chk_col; k<=chk_point; k++) {
                if($k ~ /:/) {
                        comma_num=split($k, s, ":");
                        break;
                }
        }
        return comma_num;
}
function head_string(chk_point) {
        str_buf=$3;
        for (k=4; k<chk_point; k++) {
                str_buf=sprintf("%s,%s", str_buf, $k);
        }
        return str_buf;
}

No. 4585 # まんたろう 2006/04/20 (木) 00:36:53
>>4579 べた

No.1
    m=max_desc(arglst[i],lst["${i}"]) ;
    添え字を利用した配列でいいのかな。
    あまり利用したことはないのでなんとも入れないが、こういうところで
    使えないのではないでしょうか。
    添え字にマッチする文字が出てきたときに、何かするのではなかった
    かと思います。

No.2、No.3
    多次元配列の使い方がおかしいのではないかと思います。
    データをセットする側が多次元配列や、アドレス渡しの戻りができて
    いない。たぶん、縦軸(列)の添え字の値が正しくない。
    縦軸(列)の値ってちゃんととれてますか。

No. 4586 # まんたろう 2006/04/20 (木) 00:44:59
>>4579 べた

多次元配列の使い方が正しいか問題はありますが、書き込みがあった
シェルを使用して、多次元配列で動くのを作ってみました。
一応、動きますが。

-----------------------
#!/bin/sh
#

if [ $# -eq 0 ]; then
        echo "$0 FileName"
        exit 1
fi

FILE=$1
OUT_FILE=kekka.log
rm ${OUT_FILE} > /dev/null 2>&1

nawk -v OUT=${OUT_FILE} '
function max_desc(lstadr,lst,x,y) {
        cnt=split(lstadr,arrlst,":");

        for(y=1;y<=cnt;y++) {
                lst[x,y]=arrlst[y];
        }
        return cnt;
}
{
        num=1;
        row=0;
        col=0;

        n=split($0,arglst,",");
        for(i=11;i<=n;i++) {
                ret=max_desc(arglst[i],lst,++row,col);
                if (ret>num) { num=ret; }
        }

        seqno=1;
        for(y=1; y<=num; y++) {
                for(j=1; j<=10; j++) {
                        if (j==2) {
                                printf("%d,",seqno++) >> OUT ;
                        } else {
                                printf("%s,",arglst[j]) >> OUT;
                        }
                }
                for(x=1; x<=row; x++) {
                        printf("%s",lst[x,y]) >> OUT;
                        if (x!=row) { printf("%s",",") >> OUT; }
                }
                printf("\n") >> OUT;
        }

        for(x=1; x<=row; x++) {
                for(y=1; y<=num; y++) {
                        delete lst[x,y];
                }
        }
}' ${FILE}

exit 0

-----------------------

No. 4587 # S-MSK☆ 2006/04/20 (木) 20:59:08
あるCシェルの本でファイル検査演算子「-f」の意味は
「ファイルは普通のファイル」とあるのですが、
普通の定義が分かりません。
また、逆に普通ではないファイルとはどういったもの
になるのでしょうか??
ご回答頂ければ、幸いです。
宜しくお願い致します。

No. 4588 # 68user 2006/04/21 (金) 11:02:50
>>4575 ふくし
もう解決されているとは思いますが一応。

Postfix に hosts を参照させるのが一番の早道かつ王道だと思いますが
わたしは Postfix を知らないので、識者のいるメーリングリストなどで
質問するのがよいかと思います。

>>4587 S-MSK☆
> 「ファイルは普通のファイル」とあるのですが、
> 普通の定義が分かりません。
csh 的には、stat(2) した結果の st_mode (構造体 stat のメンバ) に対して、
通常ファイル判定マクロ S_ISREG が真を返したら、「普通」です。

では S_ISREG がどういうケースで真を返すかというと、vfs の vtype の
値が VREG であるときです (vtype はファイル作成時に決定され、ファイル
システムに記録される)。

では vfs の vtype の値が VREG であるのはどういうときかというと、
ファイルシステム依存です。ただし一般的な UFS で言うと、vtype は
    1. シンボリックリンク
    2. ソケット
    3. FIFO (名前付きパイプ)
    4. デバイスファイル (キャラクタデバイス・ブロックデバイス)

    5. 通常ファイル
くらいです。よって、大抵の場合 1〜4 に当てはまらないなら通常ファイル
といえます。

実際は、Solaris Door とか、VxFS 圧縮ファイルとか、HP-UX のネットワーク特殊
ファイルなどわけのわからんのがありますので、プログラムとしては
    「1〜4 に当てはまらない場合は通常ファイル」
などという仮定はせず、素直に -f を使いましょう。

No. 4590 # 星野 2006/04/23 (日) 18:05:21
UNIX環境のAとBというプロセス間でsocket通信を行っています。(AF_UNIX指定)
一度、ソケットをcloseして、Bが再接続(connect)するとエラーになる場合があります。
errnoが何で返却されているのかわからないのですが。
たとえばEADDRINUSE の場合の対応策を教えて下さい。

No. 4591 # いち 2006/04/24 (月) 21:51:46
番号を昇順に並び替えて、抜けている番号を表示したく、以下の様なシェル
でやってみたのですが、上手く行きません。
どうすればいいでしょうか。
Solaris8 Bシェルです。

sort test.txt | nawk -v key="" '{if(FNR!=0 && $1!=key) print $1 ; key=$1}'
sort test.txt | nawk -v key="" -F"," '{if(FNR!=0 && $1-1!=key) printf("%0.4d\n",key+1); key=$1}'
sort test.txt | nawk -v key="" -F"," '{if(FNR!=0 && $1!=key) printf("%0.4d\n",key+1); key=$1}'

# cat test.txt
0006
0009
0004
0010
0003

結果
0001
0002
0005
0007
0008
と表示したい。

No. 4592 # いち 2006/04/25 (火) 16:52:15
>>4591 いち

nawk -v key=1 '{ for(;;){if($1!=key) {print key; key++;} else{key=$1+1; break;}} }' a.txt
でできました。

No. 4593 # S-MSK☆ 2006/05/01 (月) 14:44:56
>>No. 4588 68user
No.4587のS-MSK☆です。
ご回答有難う御座いました。

No. 4594 # shimizu [E-mail] 2006/05/04 (木) 11:04:32
FTP クライアントを作ってみよう (1) FTP プロトコルの概略

No. 4595 # shimizu [E-mail] 2006/05/04 (木) 11:05:02
>管理人様

FTP クライアントを作ってみよう (1) FTP プロトコルの概略

が大変勉強になりました。ありがとうございました。

No. 4596 # くるみんパパ 2006/05/10 (水) 11:59:59
vmstatをファイルへ出力する時に、1行毎に日時を編集したいのですがうまく出来ません。AIXですと下記のスクリプトでうまくいっているのですがsoralisではどのようにしたらよいでしょうか。

vmstat $1 $2 | awk '!/kthr|---|avm/ {printf("%s | ", $0);system("date")}' >> $LOGDIR$DATE

No. 4597 # zsh 2006/05/10 (水) 13:58:02
>>4596 くるみんパパ
system関数が使いたいのであればnawkか/usr/xpg4/bin/awkを使用してください。

No. 4598 # くるみんパパ 2006/05/10 (水) 14:52:42
>>4597zshさん
nawkで解決しました。助かりました。ありがとうございました。

No. 4599 # 勉強中 2006/05/11 (木) 21:58:28
はじめまして。TCP/IPについて素朴な質問があります。
TCP/IPでは、ACKに対するSYNのタイムアウトがあり、
通常のLINUXであれば180秒ほどだと思います。
一方、telnetで存在しないIPを指定すると上記タイムアウトまでかからず、
以下のメッセージが出て接続できません。

Trying 192.168.60.113...
telnet: Unable to connect to remote host: No route to host

この場合、なぜ上記タイムアウトまで待たないのでしょうか。
telnetコマンドにて
明示的にTCPリトライ回数を指定していると考えていいのでしょうか。
また、このメッセージの意味するところはどういうところなのでしょう?
誰かご存知の方がいたらご教授願います。

No. 4600 # 68user 2006/05/11 (木) 22:19:01
>>4599 勉強中
直接的な回答ではありませんが、
    http://X68000.q-e-d.net/~68user/net/tcp-connect-1.html
をご一読ください。なお、EHOSTUNREACH が No route to host です。

No. 4601 # 勉強中 2006/05/12 (金) 00:22:27
>68userさん
早速のコメントありがとうございます。
要するにアプリケーションの実装によるということですね。
(つまり、ICMP 終点到達不可メッセージを受信した際に、
    ただちにコネクション確立を中止するかしないかというポリシーによるということ)
ちなみにftpでもtelnetと同様でした。

No. 4602 # 68user 2006/05/12 (金) 11:39:16
>>4601 勉強中
> 要するにアプリケーションの実装によるということですね。
いいえ、OS の TCP スタックの実装による、だと思います。

アプリ側で対応する、つまり TCP で接続しつつ、ICMP のエラーを解析という
ことが可能かどうかはやったことがないのでわかりませんが、少なくとも ftp や
telnet という基本的なアプリがそういう小細工をしている可能性は低いと思います。

No. 4603 # 68user 2006/05/13 (土) 19:47:43
>>4602 68user
> アプリ側で対応する、つまり TCP で接続しつつ、ICMP のエラーを解析という
> ことが可能かどうかはやったことがないのでわかりませんが、少なくとも ftp や
> telnet という基本的なアプリがそういう小細工をしている可能性は低いと思います。
ICMP のエラーを解析する必要はなかったですね。connect(2) が -1 を返したとき
EHOSTUNREACH なら再接続、などとすればアプリ側で対応できます。

とはいえ、やはり ftp や telnet がそういうことをする必然性はないと思います。

No. 4604 # COM 2006/05/16 (火) 18:01:08
はじめまして。ネットワークプログラムについて質問させてください。
リミテッドブロードキャスト(255.255.255.255へ)を行いたいのですが、sockaddr_in
のアドレス部分に上記を入れても、何故かディレクテッドブロードキャスト(私の環境
では 192.168.1.255 )になってしまいます。正しくリミテッドブロードキャストする
方法はないでしょうか。setsockopt でブロードキャストのフラグを立てる、などは
行っています。環境は FreeBSD & gcc です。
以下、重要部分の抜粋です(エラー処理などは省いています)。

struct sockaddr_in addr;
int broadcast = 1;
char buf[] = "test";
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("255.255.255.255");
addr.sin_port = htons(2000);
sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast, sizeof(broadcast) );
sendto( sock, buf, sizeof(buf), 0, (struct sockaddr*)&addr, sizeof(struct sockaddr) );

ごく普通のコードだと思うのですが、パケットをモニターすると、送り先アドレスが
ディレクテッドブロードキャストになってしまっています。アドバイスだけでもいいので
助言いただけるとうれしいです。

No. 4605 # yuukun 2006/05/25 (木) 15:21:00
はじめまして。sendmailコマンドについての質問です。
[FROM:]や[TO:]フィールドに、アドレスとはべつに別名を指定し実行したところ、
エラーが出力されました。
-------------<実行コマンド>----------------------
sendmail -t
MIME-Version: 1.0
From: hoge株式会社<hoge@hoge.co.jp>
To: huge株式会社御中<huge@huge.co.jp>
Subject: 2006年05月25日の[データ]
Content-Type: text/plain; charset=iso-2022-jp

2006年05月25日 14時53分現在の
データをお送りいたします。
.
------------------------------------------------
TOやFROMフィールドでアドレスとはべつに別名を付けることは可能なのでしょうか?
よろしくお願いします。
OS:Solaris 8

No. 4606 # kojp-jp 2006/05/29 (月) 13:17:45
以下のページの「#inlcude <stdlib.h>」、スペルミスしている様です。

    http://x68000.q-e-d.net/~68user/unix/pickup?getenv

正しくは「#include <stdlib.h>」かと…。

ご確認ください。

Prev< No. 4513〜4606> Next  [最新発言に戻る] [過去ログ一覧]