BashスクリプトはCentos 7で完全に実行されますが、Ubuntu Bionicでは失敗します。

BashスクリプトはCentos 7で完全に実行されますが、Ubuntu Bionicでは失敗します。

以下のスクリプトを見つけてください

if [ "$#" -eq 0 ]; then
  dbs=('test_db_1' 'test_db_2') 
  path='/var/backups/'
else
  dbs=( "$@" )
  path='/app/mybackups/'
fi
dbuser='test_user_name'
dbpassword='test_pass_word'
now="$(date +'%d-%m-%Y_%T')"
currentDate="$(date)"
dayToSubtract=365
cd ${path}
echo "location: $path"
for element in ${dbs[@]}
        do
                echo $element
                echo "Starting backup now for db: $element on $now"
                mongodump -u ${dbuser} -p ${dbpassword} --authenticationDatabase 'admin' -d $element --gzip --archive=${element}_$now.archive
                dateToBeRemoved=$(date --date="${currentDate} -${dayToSubtract} day" +%d-%m-%Y)
                echo $dateToBeRemoved
                fileToBeRemoved="${element}_${dateToBeRemoved}"
                echo Removing $fileToBeRemoved
                rm $fileToBeRemoved*
        done
echo All Done!
echo "location: $path"

私はこのスクリプトを毎年サーバーのデータベースをバックアップするために毎年使用してきましたが、スクリプトにコマンドライン引数を渡して手動バックアップを実行するためにも使用しました。

私は最近Ubuntuを使用して新しいサーバーを入手しましたが、次のエラーが発生しました。

daily.sh: 2: daily.sh: Syntax error: "(" unexpected (expecting "fi")

参考までに、以下のスクリーンショットを参照してください。

ここに画像の説明を入力してください。

追加後:

#!/usr/bin/env bash

ここに画像の説明を入力してください。

同じエラーが発生しました。

ここに画像の説明を入力してください。

どのbashを実行すると、次のようになります。

ここに画像の説明を入力してください。

bashの結果に基づいてshebangを追加しましたが、まだ同じ問題が発生します。 ここに画像の説明を入力してください。

現在のフォルダで実行している場合:

ここに画像の説明を入力してください。

BOM確認:

ここに画像の説明を入力してください。

Ubuntuについて: 出版社ID:Ubuntu説明:Ubuntu 18.04.3 LTSバージョン:18.04コード名:bionic

答え1

スクリプトの最初の行にshebangを追加します。(
コメントから)

#!/usr/bin/env bash 

または道を知っている場合。

#!/bin/bash

または

#!/usr/bin/bash

どこにいても構いません。

答え2

コンテキストと詳細を追加するので、前の回答を下に残しておきます。しかし、あなたの誤解は、sh yourscriptあなたが何をしなければならないと思うのかから来たと思います。

それがすることは使用ですsh(ご存知のように、これはシステムによって異なります...)。翻訳者渡したスクリプト名について。

あなたは何ですか〜らしいしかし、計画は

sh -c "your command ... whatever it is"

sh今、なぜ次のように使用すると主張するのですか?翻訳者あなたのコメントと2つの答えでこれが間違っていると言われたとき、私は知りません。

スクリプトが実行可能で正しいハッシュバンを持ち、PATH相対パスまたは絶対パスを使用して検索または呼び出される場合働く

shしかし、通訳者の使用にこだわったら基本的に積極的にあなたを助けようとするすべての試みshは異なるので、邪魔してくださいsh -c COMMAND。あなたの通訳がBashではない場合、Bashismの使用は失敗する可能性があります(あなたが目撃したように)。

この失敗を「より安定」にしたい場合は、提案されている#!/bin/shように代わりにhashbangを使用してこれを確実に設定できます。これにより、shコマンドラインからスクリプトを渡すのと同じ結果が得られます。


ここにいくつかの質問があります。スクリーンショットには、スクリプトが実行不可能(root:rootファイルモード0644所有)が表示されます。したがって、それを使用して実行しようとすると、システム上のすべてのシェルをsh使用します。sh

失敗の理由は3つです。

  • あなたのスクリプトは実行可能ではなく、次の場所にありません。PATH
  • sh yourscript実行可能ではないので、インタプリタとして機能するようにしてくださいsh(Ubuntuの場合はdashすべてのBashismを理解していませんが)。
  • あなたのスクリプトに、「バイナリ」に使用する通訳者の手がかりをローダーに提供するハッシュバンはありません。

しかし、次のようなハッシュバンを追加すると:

#!/usr/bin/env bash 

...スクリプトに以下が含まれていないことを確認した場合品目明細実行可能であると確信している場合:

chmod +x daily_ori.sh

...そして相対パスを使用します(または現在のパスをに追加しますが、PATHこれは良いことではありません!)。

sh ./daily_ori.sh

...これしなければならない成功。あなたの質問に多くの情報が欠けていない限り。

しかし、最後のステップは疑問を提起します。shBashを呼び出すことが目的であれば、最初にスクリプトの実行に固執するのはなぜですか?ハッシュバン(ハードコーディングまたは使用env)を使用してインタプリタを見つけbash、スクリプトが実行可能であることを確認してから、通常どおりに呼び出します。


BOMを確認するには、以下を使用してください。

xxd -g 1 daily_ori.sh|head -n 2

...質問に合わせて編集してください。

関連情報