人に聞けない痔の悩み、これでスッキリ >>

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 コマンドを実行」
が問題みたいなのですが何がまずかったのでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (4件)

おはようございます。


これはおそらく先の質問
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を参照されたのだと思いますが、
はい、さようです。

> ただし、今の場合、最後に
> 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
> "
/home/fat32/ # expect コマンドの管理下でscpを実行する
コマンドの管理下でscpを実行する: Not a directory
invalid command name "こめんと"
while executing
"こめんと"

となりました。序でに

expect \"password:\" #こめんと
send \"$PASSWD\r\" #こめんと
interact
"

としてみましたら、

/home/fat32/ # expect コマンドの管理下でscpを実行する
コマンドの管理下でscpを実行する: Not a directory
usage: send [args] string
while executing
"send "xxxxxxxx\r" #こめんと"

となってしまいました。
何か勘違いしてますでしょうか?

補足日時:2004/12/07 13:16
    • good
    • 0
この回答へのお礼

どうもお陰さまで解決しました。
有難うございました。

お礼日時:2004/12/08 01:26

>expect \"password:\" #こめんと



ごめんなさい。
expect \"password:\" ;こめんと
の「こめんと」は#込みのつもりでした。
書きこんだあとに気づいたのですが、
やっぱり誤解がありましたね。

expect \"password:\" ;#こめんと
としてください。
しかし、コメントなんてイランでしょうから、けずっていいとおもいますよ。

この回答への補足

お手数お掛けしましてスイマセン。

> expect \"password:\" ;#こめんと
> としてください。
> しかし、コメントなんてイランでしょうから、けずっていいとおもいますよ。
expect -c " # expect コマンドを実行
set timeout 20
spawn scp -P 60001 $TARGET.lzh $UNAME@$HOST:/home/fat32/ ;# expect コマンドの管理下でscpを実行する
expect \"password:\" ;#こめんと
send \"$PASSWD\r\" ;#こめんと
interact
"
として、上手くいきました。感動です。 \(^o^)/
これでリモートホストに自動バックアップできます。

どうも有り難うございました。m(_ _)m

補足日時:2004/12/07 14:51
    • good
    • 0
この回答へのお礼

どうもお陰さまで解決しました。
有難うございました。

お礼日時:2004/12/08 01:25

おそらく、expect -c " のダブルクォーテーションが閉じられていないからではないでしょうか?


こんな感じで試してみて下さい。

#!/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\"
"
↑これ

この回答への補足

> send \"$PASSWD\r\"
> "
> ↑これ
閉じ「"」が必要だったのですね。

/home/fat32/ # expect コマンドの管理下でscpを実行する
コマンドの管理下でscpを実行する: Not a directory
usage: send [args] string
while executing
"send "user01\r" # login: が出たらログイン名を打ち込む"

となりました。ログイン名は不要でしたね。

補足日時:2004/12/07 13:15
    • good
    • 0
この回答へのお礼

どうもお陰さまで解決しました。
有難うございました。

お礼日時:2004/12/08 01:25

こんばんは。


エラーメッセージによると、文が閉じられてない!って怒られてますよね。

「expect -c " # expect コマンドを実行」

この「"」ダブルコーテーションって必要なんでしょうか?
必要だとしてもひとつしかない(=カッコとして成り立ってない)し¥マークもついてないのが気になりました。

※いま手元に環境がないんで私のほうでは試せません。
 すいません。

この回答への補足

ありがとうございます。

「"」の直前に「\」を入れたら
missing "
while executing
"""
spawn: not found
couldn't read file "login: ": no such file or directory
send: not found
couldn't read file "sword: ": no such file or directory
send: not found

となりました。

「"」を取っ払ったら

expect: option requires an argument -- c
usage: expect [-div] [-c cmds] [[-f] cmdfile] [args]
spawn: not found
couldn't read file "login: ": no such file or directory
send: not found
couldn't read file "sword: ": no such file or directory
send: not found

となりました。

「/usr/bin/expect -c "" # expect コマンドを実行」
としたら

spawn: not found
couldn't read file "login: ": no such file or directory
send: not found
couldn't read file "sword: ": no such file or directory
send: not found

となりました。でもspawnの行で引っかかってしまいます。
うーん、難しいんですね。

補足日時:2004/12/07 01:16
    • good
    • 0
この回答へのお礼

どうもお陰さまで解決しました。
有難うございました。

お礼日時:2004/12/08 01:25

このQ&Aに関連する人気のQ&A

お探しの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
}
...続きを読む

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

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

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

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

Aベストアンサー

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

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

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...続きを読む

Qシェルスクリプトで困っています

自分のLinuxマシン(PC1)から、イーサネットで繋がっているLinuxマシン(PC2)に、自動的にTelnetを用いてログインし、そこでいくつかの操作をするシェルスクリプトを作成中です。

Telnetでログインした後、PC2が持っているプログラムを走らせ、その結果を見て再度そのプログラムを走らせるか、次のプログラムへ移るかを、ユーザのキーボード入力にて判断可能なようにしたいと思っています。

"#!/usr/bin/expect"の、
"expect *** { send **** }"などを使えば、Telnetのような対話型アプリケーションに使えることが分かったのですが、ユーザからのキーボード入力を判定する方法が分かりません。。。

また、"#!/bin/sh"の、"read"コマンドを用いれば、ユーザからのキーボード入力を受け付けることが分かったのですが、Telnetなどをどう扱えばいいのかが分かりません…。

大変あいまいで、分かりにくい質問で申し訳ないのですが、どなたかお分かりになる方がいらっしゃればご教授ください。
分かりにくい点はいくらでも補足いたします。よろしくお願いいたします。

自分のLinuxマシン(PC1)から、イーサネットで繋がっているLinuxマシン(PC2)に、自動的にTelnetを用いてログインし、そこでいくつかの操作をするシェルスクリプトを作成中です。

Telnetでログインした後、PC2が持っているプログラムを走らせ、その結果を見て再度そのプログラムを走らせるか、次のプログラムへ移るかを、ユーザのキーボード入力にて判断可能なようにしたいと思っています。

"#!/usr/bin/expect"の、
"expect *** { send **** }"などを使えば、Telnetのような対話型アプリケーションに使...続きを読む

Aベストアンサー

expectではあまり複雑なことをした経験が無いのですが、
マニュアルを読むと、expect_tty や expect_user といったサブコマンドを使うと出来るように見えます。

Qapt-get install ****** でinstallしたものをuninstallするには?

御世話になります。
vncserverだけをinstallするつもりが
誤って
apt-get install vncとうってしまいました。
これをuninstallしたいのですが
どのようにすればよろしいでしょうか?

教えて下さい。

Aベストアンサー

# apt-get remove パッケージ名
では、設定ファイルは削除されずに残ります。

完全に削除するときは、
# apt-get --purge remove パッケージ名
です。

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

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シェルでsyntax errorがでてしまう

温度管理をするため、CentOS4.4上で下記のようなスクリプトを動かしています。

---スクリプト始まり---
#!/bin/bash
date=$(date '+%Y/%m/%d(%a)/%R')
rh=$(/var/usbrh/usbrh -1 2>&1)
limit=35
rh_judge=$(echo $rh | cut -c14-15)
if (( ${rh_judge} >= ${limit} )) ;then
alert=alert
else
unset alert
fi
echo ${date} ${rh} ${alert} >> /var/usbrh/usbrh_tes2.log
---スクリプト終わり---
このスクリプトで、ログを出力し、limit以上の数値になった場合、alertがログに書き込まれるようにできました。
そこでコレを少し改良してalert時にメールを飛ばせる様にしたいと思い下記のようにif文を差し替えました。

---if文始まり---
if (( ${rh_judge} >= ${limit} )) ;then
alert=alert
address="xxx@hogehoge.com"
subject="TemperatureAlert"

mail -s $subject $address << END
`$rh`
END
else
unset alert
fi
---if文終わり---

ところが、
echo ${date} ${rh} ${alert} >> /var/usbrh/usbrh_tes2.log
のあとの行(line23)で
line 23: syntax error: unexpected end of fileというのが出て
スクリプトが動かなくなってしまいました。

ログの書き込み部分は問題ないと思うのですが、原因がわかる方いらっしゃいますでしょうか。
ご指摘頂ければ幸いです。
宜しくお願いいたします。

温度管理をするため、CentOS4.4上で下記のようなスクリプトを動かしています。

---スクリプト始まり---
#!/bin/bash
date=$(date '+%Y/%m/%d(%a)/%R')
rh=$(/var/usbrh/usbrh -1 2>&1)
limit=35
rh_judge=$(echo $rh | cut -c14-15)
if (( ${rh_judge} >= ${limit} )) ;then
alert=alert
else
unset alert
fi
echo ${date} ${rh} ${alert} >> /var/usbrh/usbrh_tes2.log
---スクリプト終わり---
このスクリプトで、ログを出力し、limit以上の数値になった場合、alertがログに書き込まれるように...続きを読む

Aベストアンサー

気になるのは `$rh` かなぁ?
$rh に入っている文字列を, コマンドとして実行したいの? もしそうだとしても,
$rh | mail ...
の方が素直じゃないかなぁ.
あと, ヒアドキュメントを終わらせる END の前後に空白がないことも確認してください.

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ランキング