【復活求む!】惜しくも解散してしまったバンド|J-ROCK編 >>

test.sh

#!/bin/sh
expect -c "
set timeout -1
spawn telnet $1
expect "login:" ; send \"username\r\"
expect "sword:" ; send \"password\r\"
expect ${1} ; send \"start shell\r\"
expect ${1} ; send \"set val=`date +%Y'-'%m%d`\r\"
expect ${1} ; send \"echo $val\r\"
expect ${1} ; send \"exit\r\"
expect ${1} ; send \"exit\r\"
exit
"

例えばリモートホスト側で
コマンド date +%Y'-'%m%d
の実行結果を valに代入したいのですが

代入結果をechoコマンドで表示させても上記コマンド実行結果が
変数に代入されていないのか何も表示されません

リモートホストに変数valを表示させるのがうまくいっていないんじゃないかと
思うのですが特殊文字($val)を正しく変数として解釈させる方法をご教示いただけませんでしょうか?

A 回答 (1件)

setコマンドを使っているということは、ログイン先はcshということで合ってますか?



expect ${1} ; send \"echo $val\r\"
のところは、
expect ${1} ; send \"echo \$val\r\"
に直せばいいと思います。\ を付けないと、このスクリプトを実行する環境での $val に置き換わります。
    • good
    • 1
この回答へのお礼

notnotさん

コメントありがとうございます。

リモートシェルは、JUNOSが載ってるルータでcshではないのですが
おっしゃる通りsetコマンド使わないといけないのでcsh系です

ルータ側では問題ないのですがスクリプトを置けないため
リモートからハンドルするしかなくて

ご指示の通り$をエスケープしてみたんですが、実行結果は以下のようになりました

% set val=20110202
% can't read "val": no such variable
while executing
"send "echo $val\r""

リモートホストに渡す前に$が解釈されてしまってるような気がします


また、エスケープしていないときは以下の通りです

% set val=20110202
% echo

% exit
exit

お礼日時:2011/02/02 13:40

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qexpectの使い方について

expectの使い方についてご教示頂きたいことがあります。
内容は以下の通りです。

1)スイッチ機器にtelnetし、自動的に設定を行うようにしたい。
この機器の通常のプロンプトは"goo#"とする
"goo"はあらかじめ変数"host"として代入される。
telnet後、この装置のプロンプトが本当に goo#だったら"save"コマンドを実行する。

expect "${host}#"
send "save\n"

ここまではわかるのですが、ではgoo# 以外のプロンプトだったら即座に処理を中断
(別の処理)したいのです。


2)ログイン中に別ファイルを呼び出し、その中から1行ずつ抜き出して改行コードつきでコマンドを実行したい場合どうすればいいのか


http://www.linux.or.jp/JM/html/expect/man1/expect.1.html

このページは読んだのですが、いまいちよく理解できません。
よろしくお願いいたします。

Aベストアンサー

どもです。
参考にしてみてください。

#!/usr/local/bin/expect

set host "192.168.1.10"
set prompt "prompt"
set passwd "passwd"

set timeout -1
log_file expect.log
if [catch {open "./cmd.txt" r} fd] {
 puts "Can't open cmd.txt...\n"
 exit
}

spawn telnet $host
expect {
 "Connection timed out" {puts "\n\nTime out....\n"; exit}
 "password:"
}
send "$passwd\r"
expect {
 "Permission denied" {puts "\n\nPassword Invalid...\n"; exit}
 $prompt
}
while {[gets $fd line] >= 0} {
 send "$line\r"
 expect $prompt
}
send "exit\r"
expect eof
close $fd

どもです。
参考にしてみてください。

#!/usr/local/bin/expect

set host "192.168.1.10"
set prompt "prompt"
set passwd "passwd"

set timeout -1
log_file expect.log
if [catch {open "./cmd.txt" r} fd] {
 puts "Can't open cmd.txt...\n"
 exit
}

spawn telnet $host
expect {
 "Connection timed out" {puts "\n\nTime out....\n"; exit}
 "password:"
}
send "$passwd\r"
expect {
 "Permission denied" {puts "\n\nPassword Invalid...\n"; exit}
 $prompt
}
...続きを読む

Q自動パスワード入力でscpするスクリプトでエラー「Unterminated quoted string」

Win2kのCygwinで下記のスクリプトを試してみました。

(ローカルのファイルをscpで自動転送)

$ uname -a
CYGWIN_NT-5.0 upsil 1.5.11(0.116/4/2) 2004-09-04 23:17 i686 unknown unknown Cygwin

$ cat ./test.sh
#!/bin/sh
HOST=192.168.1.105 # scp するマシン名を設定
UNAME=user01 # ログイン名を設定
PASSWD=xxxxxxxx # パスワ-ドを設定
TARGET=/cygdrive/c/cygwin/home/root/hoge
/usr/bin/zip -r $TARGET.lzh $TARGET
expect -c " # expect コマンドを実行
set timeout 20
spawn scp -P 60001 $TARGET.lzh $UNAME@$HOST:/home/fat32/ # expect コマンドの管理下でscpを実行する
expect login:\ ; send \"$UNAME\r\" # login: が出たらログイン名を打ち込む
expect sword:\ ; send \"$PASSWD\r\" # password: が出たらパスワ-ドを打ち込む
#expect \"$\" ; send \"ls\r\" # $ が出たら ls を打ち込む
#expect \"$\" ; send \"exit\r\" # $ が出たら exit を打ち込む

$ which expect
/usr/bin/expect

$ which zip
/usr/bin/zip

$ ./test.sh
と実行すると
: 9: Syntax error: Unterminated quoted string
となり、終ってしまいました。
「expect -c " # expect コマンドを実行」
が問題みたいなのですが何がまずかったのでしょうか?

Win2kのCygwinで下記のスクリプトを試してみました。

(ローカルのファイルをscpで自動転送)

$ uname -a
CYGWIN_NT-5.0 upsil 1.5.11(0.116/4/2) 2004-09-04 23:17 i686 unknown unknown Cygwin

$ cat ./test.sh
#!/bin/sh
HOST=192.168.1.105 # scp するマシン名を設定
UNAME=user01 # ログイン名を設定
PASSWD=xxxxxxxx # パスワ-ドを設定
TARGET=/cygdrive/c/cygwin/home/root/hoge
/usr/bin/zip -r $TARGET.lzh $TARGET
expect -c " # expect コマンドを実行
set timeout 20
spawn ...続きを読む

Aベストアンサー

おはようございます。
これはおそらく先の質問
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1115230
の参考URLを参照されたのだと思いますが、
私もそのままではうまくいきませんでした。
そのURLの例は間違っているのだと思います。
(動かした後でコメントをいれて、動作確認をしなかったのかな?)
ちなみにコメントを入れる場合は下のように、行末に;
をつけてから入れるとよいようです。

基本的にエラーの原因は#2さんのご指摘のとおりです。
参考URLも良く見ると最後に"がありますよ。(それでも動かないと思いますが。。。)
ただし、今の場合、最後に
interact
を入れないとうまく動かないとおもいます。(少なくとも私はそうでした。)
この掲示板の過去の質問が参考になりました。
http://oshiete1.goo.ne.jp/kotaeru.php3?q=924035
http://oshiete1.goo.ne.jp/kotaeru.php3?q=925167

#!/bin/sh
HOST=192.168.1.105
UNAME=user01
PASSWD=xxxxxxxx
TARGET=/cygdrive/c/cygwin/home/root/hoge
/usr/bin/zip -r $TARGET.lzh $TARGET
expect -c "
set timeout 20
spawn scp -P 60001 $TARGET.lzh $UNAME@$HOST:/home/fat32/ ;こめんと
expect \"password:\" ;こめんと
send \"$PASSWD\r\" ;こめんと
interact
"

参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=924035
http://oshiete1.goo.ne.jp/kotaeru.php3?q=925167

おはようございます。
これはおそらく先の質問
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1115230
の参考URLを参照されたのだと思いますが、
私もそのままではうまくいきませんでした。
そのURLの例は間違っているのだと思います。
(動かした後でコメントをいれて、動作確認をしなかったのかな?)
ちなみにコメントを入れる場合は下のように、行末に;
をつけてから入れるとよいようです。

基本的にエラーの原因は#2さんのご指摘のとおりです。
参考URLも良く見ると最後に"がありますよ。(それでも動か...続きを読む

Qsedの置換文字に変数を使用したいのですが・・・

あるファイルの特定の文字を変換し、上書きをする処理を行いたいのですが、sedの置換文字に変数が渡せなくて困っています。

例:
X="a"
Y="b"
echo test.txt | sed 's/${X}/${Y/g}' >test.txt

sedでは置換文字に${X}といった変数を使用することはできないのでしょうか?

Aベストアンサー

' ・・・' で囲まれた中の$はそのままドルマークです。変数展開をするなら、'・・・'で囲んではいけません。

何も囲まないか、"・・・"で囲むかです。

Qgrepで検索文字列が完全一致した行だけ取り出す方法

grepの文字列検索で検索文字列が単語として、完全一致した行だけ取り出す方法はないでしょうか?

通常は
grep hoge hoge.txt

と打つと、hogeが含まれる行が出力されますが、今回は含まれる行ではなくて完全に文字列が一致した行だけ取り出したいのです。

例えばhoge.txtの中に
cc ghoge
kkl hogem
jjll hoge
という3行があったとしたら最後の行でhogeという文字が空白で区切られた行だけ取り出したいのです。

何かよい方法があれば教えてください

Aベストアンサー

-w オプションじゃだめですか?

参考URL:http://www.linux.or.jp/JM/html/GNU_grep/man1/grep.1.html

Qシェルスクリプトでファイル内の数値文字列を数値として扱うには

失礼します。
シェルスクリプトでファイル内のテキスト(数値文字列)を取得して、それを使って計算するにはどうすれば良いでしょうか?

str:ファイル内のテキスト(数値文字列)

res=$(( $str + 1 ))

・エラー
")syntax error: invalid arithmetic operator (error token is "


よろしくお願いします。

Aベストアンサー

bashをご使用と判断して

res=$(( $str + 1 ))
ではなく、
res=$(( str + 1 ))
だと思います。

> exprもやってみたのですが、処理が遅くなるので使いません。
興味があって以下のシェルで検証してみました。

#!/bin/bash

str=1
i=0

echo 'Using $((str + 1))'
date '+%H:%M:%S.%N'

while [ $i -lt 10000 ]
do
str=$(( str + 1))
i=`expr $i + 1`
done

date '+%H:%M:%S.%N'

exit

$ ./test.sh
Using $((str + 1))
09:18:46.290418000
09:18:56.929345000
これをexprに書き換えたところ
$ ./test2.sh
Using expr
09:19:00.302748000
09:19:19.259990000

exprだと19秒ですが、$(( 演算 )) だと10秒程度なので、演算が多くなれば確かにexprは不利ですね。

bashをご使用と判断して

res=$(( $str + 1 ))
ではなく、
res=$(( str + 1 ))
だと思います。

> exprもやってみたのですが、処理が遅くなるので使いません。
興味があって以下のシェルで検証してみました。

#!/bin/bash

str=1
i=0

echo 'Using $((str + 1))'
date '+%H:%M:%S.%N'

while [ $i -lt 10000 ]
do
str=$(( str + 1))
i=`expr $i + 1`
done

date '+%H:%M:%S.%N'

exit

$ ./test.sh
Using $((str + 1))
09:18:46.290418000
09:18:56.929345000
これをe...続きを読む

Qexpectを使って自動でSSHログインした後にコマンドを実行したいと

expectを使って自動でSSHログインした後にコマンドを実行したいと思っています。
df -hやmailqのようなコマンドは問題ないのですが、awkを利用してダラー?"$"を
入れてフィールド操作しようとするとダラーだけうまく読み込んでくれないのです。

■以下スクリプト
------------------------------------------------------------
read key
COMMAND="$key"
expect -c "
set timeout 3
spawn ssh アカウント@ドメイン
expect sword:
send パスワード\r
sleep 1
expect -re \"$\"
send \"${COMMAND}\r\"
expect logout: close
"
※クローズも正しくないみたいですが、無理やりtimeoutで閉じれているのでとりあえず。。

■実行結果
------------------------------------------------------------
spawn ssh アカウント@ドメイン
アカウント@ドメイン's password: can't read "NF": no such variable
while executing
"send "sudo awk '$NF>0' /proc/user_beancounters\r""

echoでCOMMANDを表示させるとちゃんと代入されているのです。
これがダラーを使わずに'{ptint}'とすれば問題ありません。となると
awkは問題ないので、やはり問題はダラーにあると思います。

バックスラッシュを入れてエスケープしてもダラーを二つ並べてもできません。
read "NFとなっているので、明示的に数字を入れてフィールドを指定してもだめです。


どなたかexpectのなかでダラーを読ませる方法をしりませんでしょうか。

expectを使って自動でSSHログインした後にコマンドを実行したいと思っています。
df -hやmailqのようなコマンドは問題ないのですが、awkを利用してダラー?"$"を
入れてフィールド操作しようとするとダラーだけうまく読み込んでくれないのです。

■以下スクリプト
------------------------------------------------------------
read key
COMMAND="$key"
expect -c "
set timeout 3
spawn ssh アカウント@ドメイン
expect sword:
...続きを読む

Aベストアンサー

$の前にバックスラッシュ2つ付けてください。
keyの入力で

ls -l | awk '{print \\$6}'

のようにします。

Qbashなどのシェル変数の値に改行を含める事は可能でしょうか?

タイトルの通りですが、通常のシェル変数の値として

 [prompt]$ aaa="bbb<改行>ccc"

のようなセットを行い、

 [prompt]$ echo $aaa
 bbb
 ccc
 [prompt]$

のような結果を得たいのですが、可能でしょうか。

Aベストアンサー

可能です.
というか,やってみたら出来ることがわかると思います.こんなところで聞くより早い.
なお,sh/bash系では改行文字は特にエスケープせずそのまま入れられます.

aaa='bbb
ccc'

Qpingでポートの指定

pingでIPアドレスを指定して、通信できるかどうかというのは
よく使いますが、pingでポートを指定して応答するかどうかは調べられるのでしょうか?

よろしくお願いします

Aベストアンサー

pingを含むICMPというプロトコルは、OSIの7レイヤで言うところのL2(同一セグメント内通信)とL3(IPルーティングされた通信)の両方にまたがる、ちょっと珍しいプロトコルです。

IPアドレスは指定できますが、別サブネットに属するIPアドレスに到達できればL3通信、できなければゲートウェイと呼ばれる同一サブネットに属する中継装置からの回答を得るという点でL2(MAC通信ではなく、同一セグメント内通信という意味)通信です。

ポート番号はL4で使用されるアドレスですから、L4機能の疎通確認はping(を含むICMP)ではできません。

FTPの疎通確認であれば、クライアントからサーバに対するTCP/21通信(FTP-CMD)が可能であること(サーバからクライアントへのTCP/21からの応答を含む)+サーバからクライアントに対するTCP/20通信(FTP-DATA)が可能であること(クライアントからサーバへのTCP/21からの応答を含む)が必要でしょう。

監視ソフトによるものであれば、
・クライアントからサーバへのログイン(TCP/21)
・クライアントからサーバへのlsの結果(TCP/20)
で確認すればよいでしょう。

pingを含むICMPというプロトコルは、OSIの7レイヤで言うところのL2(同一セグメント内通信)とL3(IPルーティングされた通信)の両方にまたがる、ちょっと珍しいプロトコルです。

IPアドレスは指定できますが、別サブネットに属するIPアドレスに到達できればL3通信、できなければゲートウェイと呼ばれる同一サブネットに属する中継装置からの回答を得るという点でL2(MAC通信ではなく、同一セグメント内通信という意味)通信です。

ポート番号はL4で使用されるアドレスですから、L4機能の疎通確認はping(を含む...続きを読む

Qシェルスクリプトの実行、「source」と「.」の違いについて

bashのシェルスクリプトを書いています。
当方、Mac Snow Leopard を使っているため、seq コマンドがデフォルトでは使えません。
そこで、.bashrc 内に、seq 関数をあらかじめ自分で定義して、他で使い回したいと思っています。
.bashrc の中に、
function seq() {
i=$1
while [ $i -le $2 ] ; do
echo $i
let i=$i+1
done
}
と、関数を定義しました。
seq 関数をターミナル上で実行すると、
>seq 0 2
0
1
2
と正しく、表示されます。次に、

#!/bin/sh
seq 0 2

と記述したシェルスクリプト(temp.sh)を「source」で実行すると、
>source temp.sh
0
1
2
と正しく、表示されますが、「.」で実行すると、
>./temp.sh
./temp.sh: line 2: seq: command not found
と言われます。
どのような理由によってこの違いが出るのでしょうか??

bashのシェルスクリプトを書いています。
当方、Mac Snow Leopard を使っているため、seq コマンドがデフォルトでは使えません。
そこで、.bashrc 内に、seq 関数をあらかじめ自分で定義して、他で使い回したいと思っています。
.bashrc の中に、
function seq() {
i=$1
while [ $i -le $2 ] ; do
echo $i
let i=$i+1
done
}
と、関数を定義しました。
seq 関数をターミナル上で実行すると、
>seq 0 2
0
1
2
と正しく、表示されます。次に、

#!/bin/sh
seq 0 2

...続きを読む

Aベストアンサー

追記

source は現在のシェルで実行し、結果がそのまま現在のシェルに適応されます。
今回の temp.sh なら
> source temp.sh

> seq 0 2
と入力したのと同等ということになります。

> ./temp.sh
この . はコマンドではなく、 temp.shへのパスを指定するものです。
実行ファイル名だけでコマンドとして実行できるのは、環境変数PATHで指定したディレクトリにあるものだけです。それ以外は、その実行ファイルへの絶対パス、または相対パスが必要となります。
これは、カレントディレクトリにある実行ファイルも例外ではありません。
環境変数PATHに . が無い場合は、 ./ファイル名 と相対パスを指定する必要があります。
(この点は、常に . がPATHにあるように振る舞うMS-DOSやコマンドプロンプトとは違います)
逆に、PATH上にあれば(例えば、 PATH=$HOME/bin:(以下略)となっている時の $HOME/bin )、 temp.sh とファイル名だけで実行できます。

また、こうしたコマンドは新規プロセスで実行されますので、環境変数を除いて、現在の設定は継承されません。
対話的ではないbashや、 shとして起動された bash は .bashrcを読まないので、そこに書いてあることは無効となります。

追記

source は現在のシェルで実行し、結果がそのまま現在のシェルに適応されます。
今回の temp.sh なら
> source temp.sh

> seq 0 2
と入力したのと同等ということになります。

> ./temp.sh
この . はコマンドではなく、 temp.shへのパスを指定するものです。
実行ファイル名だけでコマンドとして実行できるのは、環境変数PATHで指定したディレクトリにあるものだけです。それ以外は、その実行ファイルへの絶対パス、または相対パスが必要となります。
これは、カレントディレクトリにある実行...続きを読む

Qsedなどで、特定の文字列の後の文字列を抽出したい

sedなどで、特定の文字列の後の文字列を抽出したい

シェルスクリプト内で、sedなどを使って特定の文字列の後の文字列を抽出したいのですが、どうすればいいでしょうか?

たとえば、abcXYZ123defghiのなかから、XYZの後の「123」を抜き出したいです。

echo abcXYZ123defghi | sed ...

のようにして実行させたいです。

Aベストアンサー

日本語対応sedだと日本語数字混じりでもできますね。

echo abcXYZ12357defghi | sed -e 's/^.*XYZ\([0-90-9]*\).*$/\1/' -e 'y/0123456789/0123456789/'
12357

※ 使っている日本語コードの指定は必要かも(例えば、 --ctype=EUC)

echo abcXYZ12357defghi | sed -e 's/^.*XYZ\([0-90-9]*\).*$/\1/'
12357

※ 入力フォームに書いている時はASCIIと日本語の判別がし易いけど回答見るとわかり難いですね。後ろの例での結果57とy/0123456789/の数字部分が日本語です。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング