トップページunix
1001コメント327KB

シェルスクリプト総合 その9

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2007/08/15(水) 07:25:02
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。


□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashなので特に注意。
・csh/tcshのシェルスクリプトは推奨されません。
(理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
 manや参考リンクを見ましょう。
 aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)

□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。

前スレ
シェルスクリプト総合 その8
http://pc11.2ch.net/test/read.cgi/unix/1171517324/
0069名無しさん@お腹いっぱい。2007/09/12(水) 13:21:31
>>68
>>67
0070名無しさん@お腹いっぱい。2007/09/12(水) 13:32:35
>>67 に補足すると、ジョブコントロール可能なシェルのコマンドラインから
直接起動する場合に限り、バックグラウンドで起動してもSIGINTは無視されない。
しかしこれは例外と考えるべき。

ジョブコントロールは、プロセスグループを変更することによって管理していて、
fgでフォアグラウンドになる時のために、
SIGINTを無視しないようになっているだけの話。
0071652007/09/12(水) 13:42:08
レスTHXです。
shのソースを見てましたが、確かにバックグラウンドで起動されたときは
SIGINT,SIGQUITをSIG_IGNしているみたいです。

ひとつ賢くなりました。
daemonで起動することにします。
0072名無しさん@お腹いっぱい。2007/09/12(水) 16:01:50
/home/hoge/file
のfileだけ返すようなコマンドってないでしょうか。

0073名無しさん@お腹いっぱい。2007/09/12(水) 16:21:27
basename
0074名無しさん@お腹いっぱい。2007/09/12(水) 16:47:52
awk -F/ '{ print $4 }'
0075名無しさん@お腹いっぱい。2007/09/12(水) 16:53:28
>>74
アフォか。/hoge/hage/boke/file だったらどうすんだよw
0076名無しさん@お腹いっぱい。2007/09/12(水) 16:55:41
>>73
サンクスです!!
0077名無しさん@お腹いっぱい。2007/09/12(水) 16:55:49
>>75
後からそんな条件追加されてもな。
0078名無しさん@お腹いっぱい。2007/09/12(水) 17:06:15
条件追加なんかしてないじゃん。
正解が出る前にわざとボケるならまだしも、
>>73 に正解が出た後でボケてもウケないよ。
0079名無しさん@お腹いっぱい。2007/09/12(水) 17:38:55
find / -regex "/home/.*\.c"

find /home -regex "/home/.*\.c"
ってCPUやHDDへの負荷って変わりますか?
後者の方が良い気がしますが、現在全て前者で作っちゃってます。
0080名無しさん@お腹いっぱい。2007/09/12(水) 18:27:30
>>79
やってみればすぐわかるのに

あと、cのソース探すのに、-regexは過剰だろ。-nameで十分
0081名無しさん@お腹いっぱい。2007/09/12(水) 18:30:50
自分では違いに気がつかなくて人に質問しなければわからないほどの差なのであれば
どっちでもいいんじゃないかな。たまには痛い目を見るのもいい経験だよ。
0082612007/09/12(水) 18:33:59
awkについて勉強しました。
ありがとうございます。
今回のケースはこれでいけそうです。

何度もすいません、今後のために聞いておきたいのですが、
/home/hoge/abc.txt
の.txtを除いたファイル名、つまりabcを取得したい場合、
などには
どんな方法があるでしょうか。
0083名無しさん@お腹いっぱい。2007/09/12(水) 18:37:19
basename
0084612007/09/12(水) 18:42:02
basename では abc.txt とならないでしょうか。
abc.txt ではなく、 abc を取得したいと思います。
0085名無しさん@お腹いっぱい。2007/09/12(水) 18:50:29
man basename
0086名無しさん@お腹いっぱい。2007/09/12(水) 18:57:34
>>85
それだとなんか英語のようなものが表示さ(ry
0087名無しさん@お腹いっぱい。2007/09/12(水) 18:59:40
こんな初心者の質問いちいちめんどくさいから、
黙らせるためにずばり答え書いてやれよ。

basename /home/hoge/abc.txt .txt
0088612007/09/12(水) 19:06:57
そ、そんな言い方ひどいよ!!!!













サンクスです
0089名無しさん@お腹いっぱい。2007/09/12(水) 19:11:12
もうひとつ教えてやろう。
>>61 は awkなんか使わなくてもできる。

basename `dirname /home/hoge/1.txt`
0090名無しさん@お腹いっぱい。2007/09/12(水) 22:20:18
1時間ごとにのsyslog、messegesを
監視(ここでは適当なcommand)したいです。

syslogやmessegesはローテートしているので
前回の監視(1時間前)後にログが切り替わった場合と
そのまま使われている場合で実行commandを変えたいのですが
どのようなシェルスクリプトにしたらできるでしょうか?

たとえばどのログも切り替わっていない場合はcommandA、
syslogが切り替わった場合はcommandB、
messegesが切り替わった場合にはcommandCを
実行するというようなシェルスクリプトが書きたいのですが^^;
0091名無しさん@お腹いっぱい。2007/09/12(水) 22:36:41
今時のPOSIX準拠のshellだったら、外部コマンドなんか使わなくてもできる。
name=/home/hoge/1.txt; name=${name#/*/}; echo ${name%%/*}
0092名無しさん@お腹いっぱい。2007/09/12(水) 22:39:40
>>90
どっちも切り替わった場合は?

というのは置いといて、
前回と今回見ているファイルの実体同じかどうかのチェックということなら、
切り替え時に必ずi-node番号が変わるという前提で、
ls -iでi-node番号を取得して、保存しとくしかないだろうな。

oldinode=`cat /var/log/oldinodestore`
ls -i /var/log/syslog | awk '{print $1}' >/var/log/oldinodestore
newinode=`cat /var/log/oldinodestore`
if [ $newinode -eq $oldinode ]; then
kawattenai
else
kawatta
fi
0093名無しさん@お腹いっぱい。2007/09/12(水) 22:44:43
>>59
あってるだろがwwwwwwwwwww
ばかかwwwwwwwww
0094名無しさん@お腹いっぱい。2007/09/12(水) 22:50:16
>>93
あってねーよ。池沼。WWWW
(echo " aaa"; echo " bbb")|while read line; do echo $line; done
0095名無しさん@お腹いっぱい。2007/09/12(水) 22:55:10
>>90
切り替わってなくて commandA を実行しはじめたとたんに、
あるいはその直前に、切り替わっても問題ないという前提か?
0096902007/09/13(木) 10:35:28
お返事が遅くなってしまいました。

>>92
ありがとうございます。
いただいたShellで試してみますね。
いつか自分でもShellがすらすら書けるようになるのかなぁ。。

>>95
そこまでシビアなタイミングは前提にしていないようです。
最悪1時間後の監視でひっかかればよいという前提です。

>90を訂正します。
syslog、messegesどちらが切り替わってもcommandBを
実行すればよいみたいです。
syslog、messegesが切り替わっていたらcommandBを実行。
切り替わっていなかったらcommandAを実行できればよいようです。



0097名無しさん@お腹いっぱい。2007/09/13(木) 10:40:56
Shellってゆーな
0098902007/09/13(木) 10:49:31
そうでしたね^^;
先日区別しなくてはいけないと読んだばかりでした><
0099名無しさん@お腹いっぱい。2007/09/13(木) 13:00:29
>>90
>1時間ごとにのsyslog、messegesを
>監視(ここでは適当なcommand)したいです。

新人君かな?それじゃなきゃ、おわってるけどw
君には、このギョーカイ向いて無いぞ

でも、そんなの関係ねぇー♪なら、いいけどさ。

分からないことは、聞くんじゃ無くて検索するようにすれば、生き残っていけるから頑張れ!!
0100名無しさん@お腹いっぱい。2007/09/13(木) 13:23:47
>>99

新入社員です^^;


シェルスクリプトを勉強し始めましたが
自分で作れるほどにはなっていなくて><
0101名無しさん@お腹いっぱい。2007/09/13(木) 18:09:32
緊急なんだ、誰かいい知恵を貸してはもらえませんか?

CPU使用率を跳ね上げた状態で試験がしたいのです。
それで、CPU使用率がバカ上がる(目標90%)シェルかスクリプトを簡単に作りたいんです。

Whileでfindやgrepやsortをまわしたんですが、70%越えが精一杯。
もっと凶悪なものないでしょうか?
0102名無しさん@お腹いっぱい。2007/09/13(木) 18:19:13
>>101
while :; do :; done
とかは?
0103名無しさん@お腹いっぱい。2007/09/13(木) 18:21:52
>>102
whileで無限ループはかけてますよ。
0104名無しさん@お腹いっぱい。2007/09/13(木) 18:33:29
いやその、IO待ちなどが発生するコマンドを起動するんじゃなくて、
単にシェルのなかでビジーループするだけのほうがCPU占有するだろうと
思えるから書いたんだが。
0105名無しさん@お腹いっぱい。2007/09/13(木) 18:44:01
>>102 で正解だよ。
>>103 みたいな、恩を仇で返すような質問者にはなりたくないなぁ
0106名無しさん@お腹いっぱい。2007/09/13(木) 19:03:59
実はcoreが2個あるとエスパー

0107名無しさん@お腹いっぱい。2007/09/13(木) 19:06:19
hoge() { hoge & hoge; }; hoge

実験注意
0108名無しさん@お腹いっぱい。2007/09/13(木) 19:13:45
やあ (´・ω・`)

ようこそ、バーボンハウスへ。
このしょっぱいロールケーキはサービスだから、まず食べて落ち着いて欲しい。

実は、君に一生セクロス出来ない呪いをかけたんだ。
うん、「また」なんだ。済まない。
仏の顔もって言うしね、謝って許してもらおうとも思っていない。

↓このスレに「こんばんは、プッシーキャットです」とレスすれば呪いは解ける。
http://ex21.2ch.net/test/read.cgi/voiceactor/1189073996/


じゃあ、注文を聞こうか。
01091022007/09/13(木) 19:29:23
>>103-105
すみません、無知だったもので勘違いしてしまいました。
それで組んでやってみます。

ほんとありがとうございます。
0110名無しさん@お腹いっぱい。2007/09/13(木) 20:02:20
>>109
どうでもいいが、君は>>101かな?
レス番ずれとるぞ
0111名無しさん@お腹いっぱい。2007/09/13(木) 23:40:34
>>94
それのどこがファイル表示してんだ?wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
ばかばっかりwwwwwww
0112名無しさん@お腹いっぱい。2007/09/14(金) 00:12:41
    _, ._
  ( ・ω・)んも〜
  ○={=}〇,
   |:::::::::\, ', ´
、、、、し 、、、(((.@)wwwwwwwwwww
0113名無しさん@お腹いっぱい。2007/09/14(金) 00:36:44
>>111
 >>94は「行頭行末の空白が出ない」って言いたいんだろ。 >>60 参照。
0114名無しさん@お腹いっぱい。2007/09/14(金) 19:39:12
シェルスクリプトって、キーボードから入力する代わりに
ファイルからコマンドラインを読み込んでるだけですよね?
だったら、なぜシェルスクリプトのモード(?)の時は、
プロンプトが出ないんですか?
プロンプトを出す方法はありますか?
0115名無しさん@お腹いっぱい。2007/09/14(金) 20:25:19
ランダムな時間、例えば1分〜30分程度の間でランダムにsleep
させたいのですが、bashで乱数を発生させるのにはどうすれば
良いでしょうか?

何に使うかというと、

OSはCentOS5.0です。NFSサーバが一台、NFSクライアントが100台です。
NFSクライアントの個々のlocal HDDのファイルを土曜深夜に
自動バックアップさせようと思っていますのでcrontabに一行
書こうと思っています。1台あたりのバックアップは10秒もか
かりません。

うんで、100台が一斉にバックアップはじめるとサーバが死ぬので
ランダムにsleepを居れたいのですが、、、

100台のcrontabの時間を1分刻に変更してくなんて、めんどくさい
にょろ。
0116名無しさん@お腹いっぱい。2007/09/14(金) 20:27:50
>>115

sleep $((RANDOM*1800/32768))
01171152007/09/14(金) 20:30:51
>>116
ありがとうございました。
0118名無しさん@お腹いっぱい。2007/09/14(金) 20:32:04
ばっしゅ、うぜーーーーーーーーーーーーーーーーーーーー
0119名無しさん@お腹いっぱい。2007/09/14(金) 21:03:49
>>115
次はこっちで聞こうな。
シェルスクリプト総合@LINUX Part3
http://pc11.2ch.net/test/read.cgi/linux/1184077033/
0120名無しさん@お腹いっぱい。2007/09/14(金) 21:25:44
>>114
>ファイルからコマンドラインを読み込んでるだけ

違う。
プロンプトではコマンドラインしか実行できないが、
シェルスクリプトではコマンドラインの他、
if文とかfor文とか、変数の代入とかもできるようになる。

そもそも別物なので、プロンプトは出ない。
0121名無しさん@お腹いっぱい。2007/09/14(金) 21:49:47
おいおい初心者に嘘を教えるなよ
0122名無しさん@お腹いっぱい。2007/09/14(金) 22:08:09
プロンプトからはfor文とか使えないよ。

$ for i in hoge
for: Command not found.

って出るし。
変数も使えない。

$ HOGE=hage
HOGE=hage: Command not found.
0123名無しさん@お腹いっぱい。2007/09/14(金) 22:33:15
自作自演ですか
0124名無しさん@お腹いっぱい。2007/09/14(金) 22:46:57
>>114
シェルがプロンプトを出力するのは、ユーザに入力を受け付ける事ができるようになった事を表すため。
なので、基本的にその必要のない、非対話的(>シェルスクリプトのモード)な動作をするときはプロンプトを出力しない。
この対話的、非対話的であるということは起動時に決定され移行する手段もないためスクリプト実行中にプロンプトを出力する事は出来ない。
0125名無しさん@お腹いっぱい。2007/09/14(金) 23:37:55
>>124
set -i すればプロンプト出るよw
01261242007/09/15(土) 00:25:37
>>125
そっか。知らんかった。
上の部分はおk?
0127名無しさん@お腹いっぱい。2007/09/15(土) 08:45:14
>>111
これで満足か? イケヌマ君。www

echo " aaa" >file
while read line; do echo $line; done <file
0128名無しさん@お腹いっぱい。2007/09/16(日) 21:05:08
>>122
こんなどうしようもないショボい釣り針は初めて
うっかり釣られたけど、どうやったらこんなショボいこと浮かぶの?
0129名無しさん@お腹いっぱい。2007/09/16(日) 21:08:42
>>128
本当に使えないんですが,,,
使えるようになる設定とかあるんですか???
0130名無しさん@お腹いっぱい。2007/09/16(日) 21:21:06
コマンドラインでは制御文は使えないよ。
もし使えたらおかしなことになるだろ。
例えば forだったら、doneコマンドを実行したら
doコマンドのところまで後ろにジャンプしないといけない。
コマンドラインでは、打ったコマンドを順番に実行するだけだから、
後ろに戻るような動作はできない。
forを使いたきゃ、シェルスクリプトに一旦書くしかない。
0131名無しさん@お腹いっぱい。2007/09/16(日) 21:51:01
>>129
コマンドラインでfor文を使いたければ、Cシェル系(foreach)でも使ったら?
0132名無しさん@お腹いっぱい。2007/09/16(日) 22:02:42
>>129
もしかしてマジ?そんな環境があるのか知らないけど
取り合えず以下でも受け付けない?

for x in a b; do echo $x ; done
0133名無しさん@お腹いっぱい。2007/09/16(日) 22:09:27
$ for x in a b; do echo $x ; done
for: Command not found.
x: Undefined variable.
0134名無しさん@お腹いっぱい。2007/09/16(日) 22:18:59
くだらなさ全開。

$ csh
%set prompt='$ '
$ for x in a b; do echo $x;done
for: Command not found.
x: Undefined variable.
0135名無しさん@お腹いっぱい。2007/09/16(日) 22:20:51
すまん、マジならどんな環境?/bin/shだよね?
まじですまないがググらんと原因が分からないんでパス
0136名無しさん@お腹いっぱい。2007/09/16(日) 22:26:14
cshで一般ユーザのプロンプトを$にするとかどんだけ・・・
いやプロンプトをどうするかは自由だけどね
0137名無しさん@お腹いっぱい。2007/09/17(月) 10:19:56
某、犬式配布系では cshのプロンプトのデフォが $ に設定されてるね。
0138名無しさん@お腹いっぱい。2007/09/17(月) 18:50:07
そうなんだ
でも >>129-131 の時点で自演に気付けなかった自分にorz
参りました一生romってます
0139名無しさん@お腹いっぱい。2007/09/18(火) 19:37:25
初心者です。

非常に簡単なスクリプト、たとえば以下のような場合ですが
このままでいいのですかね?

もうちょっとスクリプトらしく書けとかありません?^^;
役割果たすならシンプルが一番なのかもしれませんが
シェルスクリプトというよりコマンドの羅列なので・・


#!/bin/sh
ls -i /var/log/syslog > var/log/check.log
date >> var/log/check.log
0140名無しさん@お腹いっぱい。2007/09/18(火) 20:15:57
>>139
var/log/check.logを、わざわざ相対PATHで書いてるのはなぜ?
これだと、このシェルスクリプトを / で実行しないと
期待通り動かないよ。
もうちょっとシェルスクリプトらしくするには、
例えば↓

#!/bin/sh

CHECK_LOG=/var/log/check.log
{ ls -i /var/log/syslog; date; } > $CHECK_LOG
01411392007/09/18(火) 22:35:51
>>140
おぉー、シェルスクリプトになっていますね。
こういうのは慣れなのでしょうか^^;

相対パスになっていたのも気がつきませんでした。
これも慣れるんでしょうかね・・

がんばります。アドバイスどうもありがとうございました。
0142名無しさん@お腹いっぱい。2007/09/18(火) 23:10:07
俺だったら

#!/bin/sh

CHECK_LOG=/var/log/check.log

exec > $CHECK_LOG

ls -i /var/log/syslog
date
01431392007/09/19(水) 00:41:33
>>142
レスありがとうございます。
なるほど、execコマンドって便利そうですね。
本で読んでみましたが最初よくわかりませんでしたw
リダイレクトの章を読んでで納得^^

こんな簡単な処理でもいろんな書き方があって
奥が深いですねヽ(´ー`)ノ
0144名無しさん@お腹いっぱい。2007/09/19(水) 08:11:38
>>143
>>142 は半分ネタだろ。真に受けるなw
execリダイレクトしてしまうと、今後この後に別のコマンドを追加した場合、
すべてリダイレクトされてしまって、保守性の悪いスクリプトになる。
0145名無しさん@お腹いっぱい。2007/09/19(水) 08:29:17
/root/test.txt
/root/test.1.txt
/root/test-1.txt
があります。

find / -regex "/root/[a-z0-9\-\.]+\.txt"
としても
/root/test-1.txt
だけ見つかりません。
\.をはずすと
なぜか
/root/test-1.txtが見つかるのですが、これはなぜでしょうか?
0146名無しさん@お腹いっぱい。2007/09/19(水) 08:40:10
>>145
正規表現の [ ] の中で、\ は意味ないわけだが。\- としてもだめ。
0147名無しさん@お腹いっぱい。2007/09/19(水) 08:41:11
正規表現についてはスレ違いなのでよろしこ
01481452007/09/19(水) 08:54:43
単純に正規表現単一の問題というよりは、
find での正規表現の利用の
仕方が関係ある気がします。

perl互換の正規表現を使ってperlなどでは
[a-z-.]でいけるんですが、
find でこれを使うと Invalid range end が表示されてしまいます。
0149名無しさん@お腹いっぱい。2007/09/19(水) 09:04:42
単純に正規表現単一の問題ですね。
0150名無しさん@お腹いっぱい。2007/09/19(水) 09:33:06
>>148
find /root -regex "/root/[-.a-z0-9]+\.txt"
0151名無しさん@お腹いっぱい。2007/09/19(水) 09:35:01
root 常用すんな。
0152名無しさん@お腹いっぱい。2007/09/19(水) 18:54:59
>>107 ってなんで実験注意なの?
0153名無しさん@お腹いっぱい。2007/09/19(水) 20:16:33
>>152
見た感じfork爆弾なのかなと思ったけど、どうなんだろ。

#!/bin/sh
$0 & $0 &

でよさそーな気もする。
0154名無しさん@お腹いっぱい。2007/09/20(木) 13:26:36
{cd /tmp ; ls}
この{}の意味って何なのでしょうか?
()のサブシェルとの違いは?
0155名無しさん@お腹いっぱい。2007/09/20(木) 13:28:51
>>154
意味以前に、{ } の文法間違ってる。それでは正しく動かない。
0156名無しさん@お腹いっぱい。2007/09/20(木) 15:53:30
>>155
zshなら動くみたい

>>154
cd; foo=''; { cd /tmp; foo=bar; }; pwd; echo $foo

cd; foo=''; (cd /tmp; foo=bar); pwd; echo $foo
を実行してみればわかるかも
0157名無しさん@お腹いっぱい。2007/09/20(木) 16:21:49
zshうぜーーーーー
0158名無しさん@お腹いっぱい。2007/09/20(木) 17:31:38
シェルスクリプトで変数が使えないんですが、どうしてでしょう?
もちろん、SHELL=/bin/sh と、あらかじめ設定されてます。

#!$SHELL

echo helloworld
0159名無しさん@お腹いっぱい。2007/09/20(木) 17:35:19
  (  ゚д゚) 

  ( ゚д゚ )

  ( ゚д゚ ) 
0160名無しさん@お腹いっぱい。2007/09/20(木) 17:44:06
つまんね。
0161名無しさん@お腹いっぱい。2007/09/20(木) 17:45:31
exportし忘れてるんじゃねーの?
0162名無しさん@お腹いっぱい。2007/09/20(木) 18:00:59
zshなら動くみたい
0163名無しさん@お腹いっぱい。2007/09/20(木) 20:12:04
>>161
exportは既にしています

>>162
ありがとうございます。zshにしたら動きました
0164名無しさん@お腹いっぱい。2007/09/22(土) 18:06:21
testコマンドでファイルサイズの比較のオプションは用意されてないのでしょうか?
ls fileA | awk '{print $5}' ってな感じで抜き出して比較しないとダメですか?
0165名無しさん@お腹いっぱい。2007/09/22(土) 18:26:34
>>164
testコマンドではファイルサイズが0かどうかの判定しかできないね。
ls | awk じゃ無駄。
wc -c を使うと良い。

if [ `wc -c < fileA` -gt `wc -c < fileB` ]; then

みたいに。

wc -cの結果にファイル名が出ずにファイルサイズの数字のみになるように、
wc -c fileA じゃなくて wc -c < fileA にするのがコツ。
0166名無しさん@お腹いっぱい。2007/09/22(土) 18:48:12
MacOSX(BSD)とGNU版のマニュアルをみただけだが……
wcの-cオプションて国際化されててもバイト数を返すんだな。
-mで文字数か。
0167名無しさん@お腹いっぱい。2007/09/23(日) 00:40:46
ファイルの情報をとるなら stat コマンドも便利だが
どのへんのOSに入ってるかまでは把握してない...
0168名無しさん@お腹いっぱい。2007/09/23(日) 03:12:27
>>167
Coreutils か Shellutils じゃなかったっけ?
■ このスレッドは過去ログ倉庫に格納されています