シェルスクリプト総合 その16
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
2010/02/20(土) 14:10:05スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
Linuxユーザは/bin/shの正体がbashなので特に注意。
FreeBSDユーザは/bin/shの正体がashなので注意。
v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。
http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/
http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
(理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
manや参考リンクを見ましょう。
aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
前スレ
シェルスクリプト総合 その15
http://pc12.2ch.net/test/read.cgi/unix/1246408968/l50
0544名無しさん@お腹いっぱい。
2010/08/08(日) 22:10:40BACKUPLIST=/home/hoge/backup/sample.lst
0545名無しさん@お腹いっぱい。
2010/08/08(日) 22:18:49えっと、リストは絶対に必要なのかな?
スクリプト内に書いとくのでは駄目なのか
ファイルから読み込むとなると、どうしてもループさせることになるので色々と困るのだが…
>>543のように空白含むパス名の扱いにも問題が出る
BACKUPLIST内のディレクトリの数が数千とかじゃなければスクリプト内に書いたほうが楽
/home/abcってのはちょっとよく分からない
>>535では/home/aaa/abc、/home/bbb/abcの2つのディレクトリがあるようだけど
アーカイブを2つ作りたいってことなのかな
0546>>543
2010/08/08(日) 22:42:51なるべく、リスト内で処理したいです。
理由は、数千もディレクトリは無いにしろ数十・数百あるとかなり厳しいです。
後、スクリプト内を簡潔にしたいのもあります。
でも、>>545の言う通り数十・数百位のディレクトリならスクリプト内に
書いた方が楽なら、そちらの方がベスト!?なのかも・・・・。
確かに、両方abcとあるので分かりにくいので/home/aaa/test1と/home/bbb/test2
なら大丈夫ですかね??
/home/aaa/test1配下と/home/bbb/test2配下にあるものを1つのアーカイブで
まとめたいって事です。
0547名無しさん@お腹いっぱい。
2010/08/08(日) 22:50:31#!/bin/bash
# ${HOME}以下の相対パスを書く
l=("foo bar/" "hoge fuga/")
cd ~
mkfifo tmp.fifo
find "${l[@]}" -type f -daystart -atime '+7' \
-exec tar -cvzf $(date +%Y%m%d).tar.gz {} + -fprintf tmp.fifo '%P\n' &
while read f; do rm -f "${f}"; done <tmp.fifo
rm tmp.fifo
本当は素直にfindを2回かけて-exec tar、-deleteすればいいんだけど
条件に-atimeが入ってるので1回目と2回目のfindの結果が変わっちゃう
(findではatimeは変わらないけどtarすると変わるらしい)
なのでnamedpipeを作ってrmをwhileで回すという面倒臭いことをしてる
削除するファイルが増えればそれなりに遅くなるはず
誰かもっと良いやり方あれば教えてください
find一発で出来ないものか
0548名無しさん@お腹いっぱい。
2010/08/08(日) 23:04:24それじゃあ、ひと手間増えるけど
#!/bin/bash
backuplistfile="${HOME}/backuplist"
fifo="/tmp/backup.fifo"
while read p; do backuplist=("${backuplist[@]}" "${p}"); done <"${backuplistfile}"
cd /home
mkfifo "${fifo}"
find "${backuplist[@]}" -type f -exec tar -cvzf testbackup.tar.gz {} + -fprintf "${fifo}" '%P\n' &
while read f; do echo rm -f "${f}"; done <"${fifo}"
rm "${fifo}"
で、backuplistにはaaa/test1等と書いておけばいい
面倒だなぁ…俺てっきり>>537で行けると思ったのに
0549>>546
2010/08/08(日) 23:06:18スクリプトthx
とりあえず、なにかベストなやり方をもう少しググってみます。
他にもっとベストなやり方があればアドバイスよろしくお願いします。
0550名無しさん@お腹いっぱい。
2010/08/08(日) 23:09:52同じくスクリプトthxです。
明日ちょっと、実行させてみます。
結果はまた報告します。
0551名無しさん@お腹いっぱい。
2010/08/08(日) 23:10:520552名無しさん@お腹いっぱい。
2010/08/09(月) 14:34:410553名無しさん@お腹いっぱい。
2010/08/09(月) 14:52:50マジでっ!?
0554名無しさん@お腹いっぱい。
2010/08/09(月) 17:37:58ループから脱出(break;) したり、次の周回に飛ぶ(continue;) には、
どうするのがよいのでしょうか。
0555名無しさん@お腹いっぱい。
2010/08/09(月) 17:42:500556名無しさん@お腹いっぱい。
2010/08/09(月) 17:43:43自分で答え書いてるじゃん。
break とか continue とか実行すればいいだけ。
0557名無しさん@お腹いっぱい。
2010/08/09(月) 18:17:380558名無しさん@お腹いっぱい。
2010/08/10(火) 17:09:38mountの実行を5秒程度スクリプトのなかで遅らせたいんですが
どのようにすればよいですか?
0559名無しさん@お腹いっぱい。
2010/08/10(火) 17:43:510560558
2010/08/10(火) 22:45:52どうもです
0561名無しさん@お腹いっぱい。
2010/08/10(火) 23:18:19起動スクリプトいじるような人がまじでsleep知らなかったの?
0562名無しさん@お腹いっぱい。
2010/08/10(火) 23:29:090563名無しさん@お腹いっぱい。
2010/08/11(水) 07:33:150564名無しさん@お腹いっぱい。
2010/08/12(木) 07:22:26起動スクリプトにsleepが入ってるのは良い設計ではない。
0565名無しさん@お腹いっぱい。
2010/08/12(木) 07:34:16まあ、RHELでもこんなもんだ:
$ grep sleep /etc/init.d/* | wc -l
37
0566名無しさん@お腹いっぱい。
2010/08/12(木) 07:34:44そりゃ、RHELだもん。
0567名無しさん@お腹いっぱい。
2010/08/12(木) 07:42:15だれがgrepしてみて。
0568名無しさん@お腹いっぱい。
2010/08/12(木) 07:45:06それ、whileループ中で、あるコマンドを実行し、失敗した時のみ
sleepしてからリトライするという記述がメインなので、
通常時はsleepは実行されないし、問題ない書き方なんだよ。
0569名無しさん@お腹いっぱい。
2010/08/12(木) 12:45:45そう思うだろ?
実際見てみると、正常ルートなのに笑えるほど寝てるぜ。
0570名無しさん@お腹いっぱい。
2010/08/12(木) 12:49:580571名無しさん@お腹いっぱい。
2010/08/12(木) 13:19:05確認したけど、1番目の起動スクリプトが実行開始されてから
最後の起動スクリプトが終了するまでトータルで1秒未満なので、
sleepは1度も実行されてない。
OS起動時は、起動スクリプトの速度はネックになってなくて、
むしろ、カーネル自身のデバイス認識部分とかに時間がかかってる。
0572名無しさん@お腹いっぱい。
2010/08/12(木) 16:30:34[OK]
[OK]
・
・
・
・
が1秒以内に終わる・・・?超進化してるな。
0573名無しさん@お腹いっぱい。
2010/08/12(木) 16:52:40未だに起動が激遅なSolarisを何とかしてください。
0574名無しさん@お腹いっぱい。
2010/08/12(木) 18:59:43なぜだめなの?
0575名無しさん@お腹いっぱい。
2010/08/12(木) 19:15:53非同期処理の終了をタイミングで取る→機種依存
0576名無しさん@お腹いっぱい。
2010/08/12(木) 19:27:44単純にsleepで待ってるんじゃなくて、実際にはこういう処理だよ
↓
while ! command
do
sleep 1
done
どこにも機種依存要素はないし、
この処理で sleep を外したらそれこそ busy loop で重くなる。
0577名無しさん@お腹いっぱい。
2010/08/12(木) 19:34:39>どこにも機種依存要素はないし
こいつアホ(AAry
0578名無しさん@お腹いっぱい。
2010/08/12(木) 19:52:37いや、これ最高にアホだろ。
0579名無しさん@お腹いっぱい。
2010/08/12(木) 20:14:530580名無しさん@お腹いっぱい。
2010/08/12(木) 20:26:06ここで言う機種依存といのはハードウェア構成依存という事だろう。
0581名無しさん@お腹いっぱい。
2010/08/12(木) 20:50:29それは分かってるんだが。
大量に同一用途のサーバー管理するんでもなきゃ、
わざわざ可搬性を考慮するのなんて、バカバカしいよ。
0582名無しさん@お腹いっぱい。
2010/08/12(木) 21:19:44ぜんぜんわかってねぇなw
0583名無しさん@お腹いっぱい。
2010/08/12(木) 23:02:33反論も出来ないならひっこんでろよ
0584名無しさん@お腹いっぱい。
2010/08/12(木) 23:16:36何イライラしてるんだよw
sleep同期君
0585名無しさん@お腹いっぱい。
2010/08/13(金) 11:23:11別に問題ないと思うけど。
0586名無しさん@お腹いっぱい。
2010/08/13(金) 12:03:28そもそも非同期処理じゃないし…
0587名無しさん@お腹いっぱい。
2010/08/13(金) 12:46:070588名無しさん@お腹いっぱい。
2010/08/13(金) 13:07:37あれはタイマ割り込み使って音源鳴らしてるだけだろ。
0589名無しさん@お腹いっぱい。
2010/08/13(金) 13:08:450590名無しさん@お腹いっぱい。
2010/08/13(金) 13:43:34SMF再生するシェルが書けそうだな。
0591名無しさん@お腹いっぱい。
2010/08/13(金) 14:17:120592名無しさん@お腹いっぱい。
2010/08/20(金) 19:16:35単純に
tar directry/faile.tar tergetdir/
としてみたんですが
0593名無しさん@お腹いっぱい。
2010/08/20(金) 19:33:45シェルと関係ない話は別スレでやれよ(Makefileとも関係ないし)
まあ、f と -C オプションが落ちてるのが原因だけどな。
0594名無しさん@お腹いっぱい。
2010/08/20(金) 20:07:240595名無しさん@お腹いっぱい。
2010/08/20(金) 20:09:52faile
terget
英語初心者スレが適当だね
0596名無しさん@お腹いっぱい。
2010/08/20(金) 20:37:55オプションがないね
man tarオススメ
tar cf foo.tar bar
tar cfz foo.tar.gz bar
tar cfj foo.tar.bz2 bar
0597名無しさん@お腹いっぱい。
2010/08/20(金) 21:11:100598592
2010/08/20(金) 21:29:35tar xvfp directry/file.tar tergetdir/
でした
0599名無しさん@お腹いっぱい。
2010/08/20(金) 21:36:300600名無しさん@お腹いっぱい。
2010/08/20(金) 22:12:32だから、>>593 が言うように -C を付けろよ
0602名無しさん@お腹いっぱい。
2010/08/22(日) 09:15:580603名無しさん@お腹いっぱい。
2010/08/22(日) 09:48:130604名無しさん@お腹いっぱい。
2010/08/23(月) 22:07:15passwd(1)をシェルスクリプトでバッチ的に流すにはどうすればいいのでしょうか。
2回聞かれるところとかが、どう書けばいいのかわかりません。
お願いします。
0605名無しさん@お腹いっぱい。
2010/08/23(月) 22:13:46標準ツールじゃないけど、expect使ってみるとか。
0606名無しさん@お腹いっぱい。
2010/08/23(月) 22:26:36chpasswdってBSDには無いの?
0607名無しさん@お腹いっぱい。
2010/08/26(木) 14:17:560608シェルマスター
2010/08/28(土) 00:16:37お前らならどんなシェルスクリプトを作る?
0609名無しさん@お腹いっぱい。
2010/08/28(土) 00:48:130610名無しさん@お腹いっぱい。
2010/08/28(土) 03:14:390611名無しさん@お腹いっぱい。
2010/08/28(土) 12:19:38ログをcsvに整形してExcelのオートフィルタで分析とか。
0612名無しさん@お腹いっぱい。
2010/09/01(水) 09:09:06ただ、これだとプログラムが終了したりするとタブが閉じちゃうので、終了した後でもまたそこから
コマンドが打てるように改変したいのですがどのようにやれば良いのでしょうか?
#!bin/sh
gnome-terminal \
--tab --working-directory=`pwd`/hoge/ -e "command" \
--tab --working-directory=`pwd`/foo/ -e "command" \
--tab --working-directory=`pwd`/bar -e "command" \
一応ググってみると
gnome-terminal -x bash -c "command1; command2; exec bash"
こんな表記を使うとその後もコマンドを受け付けるみたいなのですが、
上のスクリプトとの組み合わせ方が上手くいかず、タブが起動しなかったりプログラムが起動しなかったりします。
OSはUbuntuなのでシェルはbashになると思います。お願いします。
0613名無しさん@お腹いっぱい。
2010/09/01(水) 09:34:17gnome-terminal -e 'bash -c "command1; command2; exec bash"'
0614名無しさん@お腹いっぱい。
2010/09/01(水) 17:51:34そこで、シェルで一気にプロセスをきりたいのですが、どのように記述すればいいですか?
0615名無しさん@お腹いっぱい。
2010/09/01(水) 18:06:22たぶん argument list too long とかいわれるんで、分割いるけど。
0616名無しさん@お腹いっぱい。
2010/09/01(水) 18:53:26使えるかは環境によるけど。
0617名無しさん@お腹いっぱい。
2010/09/01(水) 19:55:10そうですpkillです。
であとシェルの種類はbashでやりたいんです。
んで流れ的には612のように、1つの端末にタブで複数のプログラムを動かします。
んで複数のプログラムのプロセスをシェルを実行するだけですべてを切りたいんです。
そのようなシェルを作るにはどうすればよいですか?
ちなみに環境はubuntu10.04です
0618名無しさん@お腹いっぱい。
2010/09/01(水) 20:05:56>>613 には礼なしかよw >>613 はできたんだな?
だったら、pkill -HUP gnome-terminal とかすれば、
その gnome-terminal から派生したプロセスは(普通は)まとめて終了する。
ただし、個々のプロセス側でシグナルを無視してたり、
setsid()とかで別セッションを開始してる場合(デーモン類等)は
終了しないけど、これは仕方ない。
0619名無しさん@お腹いっぱい。
2010/09/01(水) 20:30:050620名無しさん@お腹いっぱい。
2010/09/01(水) 23:06:530621名無しさん@お腹いっぱい。
2010/09/02(木) 00:01:550622名無しさん@お腹いっぱい。
2010/09/02(木) 07:31:04>シェル作っちゃう人だし
えっ? ここの住人は自分でシェル作れないんですか?
ネットからのコピペ(+改変)専門ですか?
0623名無しさん@お腹いっぱい。
2010/09/02(木) 08:46:53シェルスクリプトは書けるけど、シェル作れる奴なんてここにはいないよ。
0624名無しさん@お腹いっぱい。
2010/09/02(木) 08:54:34難しく考えずにまずは自分でシェル作ってみたら?
ハローワールドのシェルなんてたった2行で作れるよw
0625名無しさん@お腹いっぱい。
2010/09/02(木) 08:55:030626名無しさん@お腹いっぱい。
2010/09/02(木) 09:56:23その2行のソース読ませてくれない?
何万文字で2行なんだ?
0627名無しさん@お腹いっぱい。
2010/09/02(木) 09:57:46#include <stdio.h>
#include <stdlib.h>
0628名無しさん@お腹いっぱい。
2010/09/02(木) 10:07:46スクリプトにするならperlだし。
シェルはスクリプトにはせずにコマンドとして使う。
0629名無しさん@お腹いっぱい。
2010/09/02(木) 10:11:2670文字で2行だよw
#!/bin/sh
while echo -n 'myshell> '; read line; do eval "$line"; done
0630名無しさん@お腹いっぱい。
2010/09/02(木) 10:22:08オマエくらい知能が低く生まれたかったわ
マヌケな2行でご満悦か
毎日幸せだろ?ww
0631名無しさん@お腹いっぱい。
2010/09/02(木) 10:30:44whileの後に echoなんて書いても動くわけないし、
doより前に ; なんて書いてるからここでエラーになるはず。
試さなくてもわかる。
0632名無しさん@お腹いっぱい。
2010/09/02(木) 10:38:000633名無しさん@お腹いっぱい。
2010/09/02(木) 11:44:48>>617
> すべてを切りたいんです。
とか言ってるから変換ミスではないと思う。
0634名無しさん@お腹いっぱい。
2010/09/02(木) 12:09:58#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
void child(int argc, char **argv);
int main()
{
int argc, n = 0;
int status;
char input[10000], *argv[256], *cp;
const char *delim = " \t\n";
0635名無しさん@お腹いっぱい。
2010/09/02(木) 12:11:09++n;
printf("[%s@2ch]$ ", getenv("USER"));
if (fgets(input, sizeof(input), stdin) == NULL || input == 4) {
exit(0);
}
cp = input;
argc = 0;
while (argc < 256) {
if ((argv[argc] = strtok(cp,delim)) == NULL)
break;
cp = NULL;
argc++;
}
0636名無しさん@お腹いっぱい。
2010/09/02(木) 12:12:14exit(0);
}
pid_t pid = fork();
if(pid == -1) {
perror("fork");
exit(1);
} else if(pid == 0) {
child(argc, argv);
} else {
wait(&status);
}
}
}
void child(int argc, char **argv) {
execvp(argv[0], argv);
}
0637名無しさん@お腹いっぱい。
2010/09/02(木) 17:50:530638名無しさん@お腹いっぱい。
2010/09/02(木) 17:54:12input == 4 ← inputは char *型なのに
とか、
execvp(argv[0], argv)
の引数が足りないとか、
間違いがあるとネタにもならんな。
0639名無しさん@お腹いっぱい。
2010/09/02(木) 18:02:38int main(){char b[256];while(printf("hoge> "),gets(b)){system(b);}return 0;}
コンパイル、動作確認済み。warning無視
0640名無しさん@お腹いっぱい。
2010/09/02(木) 19:07:59#include </dev/tty>
0641名無しさん@お腹いっぱい。
2010/09/02(木) 19:18:510642名無しさん@お腹いっぱい。
2010/09/02(木) 19:22:23「シェルできました」と言うのはちょっとなぁ。
0643名無しさん@お腹いっぱい。
2010/09/03(金) 08:44:51シェルを書く話はよそでやってください。
■ このスレッドは過去ログ倉庫に格納されています