質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Tera Term

Tera Termは、TeraTerm Projectが開発する国産のWindows向けターミナルソフト。telnetプロトコルでのリモートホストへの接続やCOMポートのシリアル接続が可能で、マクロが利用できます。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Q&A

解決済

2回答

799閲覧

ShellScriptでkubernetesのcronjob更新を実施したい

python_heroku

総合スコア23

Tera Term

Tera Termは、TeraTerm Projectが開発する国産のWindows向けターミナルソフト。telnetプロトコルでのリモートホストへの接続やCOMポートのシリアル接続が可能で、マクロが利用できます。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

0グッド

0クリップ

投稿2023/03/08 12:02

編集2023/03/08 14:32

実現したいこと

  • kubectl patch cronjob NAME -p '{"spec":{"schedule":"45 20 8 3 *"}}' -n NAMESPACEをコマンドをシェルにて実行してスケジュール時刻を更新したい
  • 45 20 8 3の部分についてはshellにて現在時刻を変数として入れたい
    • 左からcronjobの実行時間である分 時 日 月の値のこと

前提

上記コマンドにて手動で実行すると更新できることは確認済み

発生している問題・エラーメッセージ

error: unabel to parse "'{¥"spec¥":{¥"schedule¥"... yaml:found unexpected end of stream

ダブルクォーとの前にエスケープ文字の¥が入ってしまい、k8s側としては想定外コマンドとして認識している、ように私は見える
ちなみに直前のecho $resultで出力される文字をコピーして実行すると意図通り実行できることは確認

該当のソースコード

shell

1schedule_time=省略(dateを用いて時刻を取得) 2echo $schedule_time 3# 上記の出力結果はこうなってる 4# 45 20 8 3 * 5 6before_text='kubectl ... "schedule":"' 7after_text='"}}...-n NAMESPACE' 8 9result=$before_text$schedule_time$after_text 10 11echo $result 12# 上記の出力結果は意図通り以下のようになっている 13# kubectl patch cronjob NAME -p '{"spec":{"schedule":"45 20 8 3 *"}}' -n NAMESPACE 14 15echo `$result` 16# これがエラーになるためのこれの解決方法を知りたい 17

教えてほしいこと

  • なぜ文字列として出力した場合、想定通りの文字になるのに、コマンドとして実行しようとするとエスケープ文字(¥)が入ってくるのか?が知りたい

  • かなり力技なソースのため可読性が悪く、別にこの形に拘っていないので、もっと賢いやり方があれば教えてほしい

    • 最初scheduleの中の数字のみ変数にして実行しようとしたが、シングルクォート内に変数を入れられず断念

その他

不足事項あればご指摘ください

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2023/03/08 12:14

> # 上記の出力結果は意図通り以下のようになっている > # kubectl patch cronjob NAME -p '{"spec":{"schedule":"45 20 8 3 *"}' -n NAMESPACE この部分ですが、"}" が足りない様に見えます。実際にはどの様になっているのでしょうか?
python_heroku

2023/03/08 14:30

コメントありがとうございます。ご指摘通りで}がこちらの質問文の中に不足していました。実機では存在しており、手動であれば問題なく実行できております。
guest

回答2

0

ベストアンサー

手元のクラスタで試してみました。
とりあえず以下で期待した動作をしました。ご参考までに。
kubectlコマンドを組み立てる時に ' で囲ってしまうと変数が展開できなくなって逆に面倒だったのでダブルクオートにしてがんばってエスケープした感じです。
エスケープで悩むようであれば、いっそのことテンポラリファイルにjsonを出力してしまって、それを kubectl patch hello --patch-file temp.json で食わせるのも悪くないアイデアかもしれません。

sh

1#!/bin/bash 2 3schedule_time="45 20 8 3 *" 4echo $schedule_time 5# 上記の出力結果はこうなってる 6# 45 20 8 3 * 7 8result="kubectl patch cronjob hello -p '{\"spec\":{\"schedule\": \"${schedule_time}\"}}' -n default" 9 10echo $result 11# 上記の出力結果は意図通り以下のようになっている 12# kubectl patch cronjob NAME -p '{"spec":{"schedule":"45 20 8 3 *"}}' -n NAMESPACE 13 14eval $result

蛇足

yaml:cronjob

1apiVersion: batch/v1 2kind: CronJob 3metadata: 4 name: hello 5spec: 6 schedule: "0 12 * * *" 7 jobTemplate: 8 spec: 9 template: 10 spec: 11 containers: 12 - name: hello 13 image: busybox 14 command: 15 - /bin/sh 16 - -c 17 - date; echo Hello from the Kubernetes cluster 18 restartPolicy: OnFailure

投稿2023/03/09 04:51

編集2023/03/09 05:04
YakumoSaki

総合スコア2027

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

python_heroku

2023/03/09 12:57

こちら実環境で試すまでして頂き、ありがとうございます! 同様にエスケープすれば実行できたことを確認できました!
guest

0

シェルのコマンドラインは、実際に指定したコマンドを実行するまで、様々な処理をされますが、
処理ごとに順番に一度ずつ処理されます。
引用符の解釈(注1)は、変数展開よりも前なので、変数展開された結果、変数の中に含まれていた"'がシェル文法的な意味での引用符と解釈されることはありません。特別な意味を持たない単なる"'という1文字と見なされます。

変数展開された結果の引用符をシェル文法的な意味での引用符と解釈させるためには、evalコマンドを使って、コマンドラインの解釈の2周目を行わせる必要があります。が、まるまるコマンドライン解釈を繰り返すので、却ってまずい解釈をされ可能性もあります。

コードの一部が書かれてないので、うまく行くかどうか考えてませんが、

sh

1echo `eval $result`

でうまく行くかも知れません。
evalによる2周目で意図しない解釈がされてうまく行かないようなら、されないように何らかの工夫が必要です。

まあ、簡単には、コマンドラインの構成要素を変数に入れないことです。

メッセージの"\"になってしまっているのは、kubectl コマンドがエラーメッセージを出力する際に、文字列を"で囲んで表示する仕様になっており、"で囲まれる文字列内に"がある場合は、文字列の終わりを示す"じゃなくて、単なる文字列の"であることを示すために、kubectl コマンドが表示の際に意図的に追加していると思われます。

注1:
引用符の解釈は、コマンドライン解釈の「単語展開」のステップで行われます。
echo aa bbだと、aabbは別単語で、echoの引数は2つです。
echo "aa bb"だと、aa bbで1つの単語で、echoの引数は1つです。
このように、どこからどこまでが1つの単語か(1つの引数か)を決めるのが単語展開で引用符の有無がそれに影響します。
A='"aa bb"'; echo $Aのようなケースだと、変数展開後の"aabb"のそれぞれ3文字の2単語が2つの引数になります。

このあたりの詳細は、man bashの展開セクションを参照(英文manだと、EXPANSIONセクション)。

投稿2023/03/08 15:17

編集2023/03/09 02:36
otn

総合スコア85927

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2023/03/08 15:24

類似例として、変数展開も1度しか行われないので、変数展開の結果の中の$は単なる文字です。evalすると2周目の変数展開が行われます。 例: A='$HOME' echo $A eval echo $A
python_heroku

2023/03/08 23:19

回答ありがとうございます。 echoのコマンド実行時に¥が入っているのではなく、echoの引数が正しく認識されていないことが問題、ということで理解しました。 一先ずevalを試してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問