2017-10-18 102 views
11

我有這個到目前爲止,但我錯過了幾個像獲取cron作業腳本的東西。不想以root身份執行此操作。所以我假設可以做更多的事情來同時設置第一個用戶。該腳本需要是冪等的(如果以前使用相同的參數運行,可以反覆運行而不會冒險改變任何內容)。在新的Ubuntu 16.04服務器上用SSL編寫新的nginx實例的正確方法是什麼?

singledomaincertnginx.sh:

#!/bin/bash 
if [ -z "$3" ]; then 
     echo use is "singledomaincertnginx.sh <server-ssh-address> <ssl-admin-email> <ssl-domain>" 
     echo example: "singledomaincertnginx.sh [email protected] [email protected] some-sub-domain.mydomain.com" 
     exit 
fi 
ssh $1 "cat > ~/wks" << 'EOF' 
#!/bin/bash 
echo email: $1 
echo domain: $2 
sudo add-apt-repository -y ppa:certbot/certbot 
sudo apt-get update 
sudo apt-get upgrade -y 
sudo apt-get install -y software-properties-common 
sudo apt-get install -y python-certbot-nginx 
sudo apt-get install -y nginx 
sudo sed -i "s/server_name .*;/server_name $2;/" /etc/nginx/sites-available/default 
sudo systemctl restart nginx.service 
if [[ -e /etc/letsencrypt/live/$2/fullchain.pem ]]; then 
    sudo certbot -n --nginx --agree-tos -m "$1" -d "$2" 
fi 
if [[ ! sudo crontab -l | grep certbot ]]; then 
    # todo: add cron job to renew: 15 3 * * * /usr/bin/certbot renew --quiet 
EOF 
ssh $1 "chmod +x ~/wks" 
ssh -t $1 "bash -x -e ~/wks $2 $3" 
+3

爲什麼不使用Ansible? –

+1

看起來不錯,問題在哪裏? – aggsol

+0

除了在here-doc裏面缺少'fi'外,看起來不錯。也許和你的''$ 1'''dbl-quoting一致?要真正防患於未然,可能需要添加一些dbl-檢查每個步驟的工作。你可以將所有'apt-get's和'&&'s(實際上所有的步驟)(是的,瘋狂的)和/或檢查日誌文件確實發生,或者捕獲Std-err並確保它是空的等等,或者你可以從事情的「完成的結局」來看它,並添加一個測試來證明你的「使用SSL的nginx實例」按需要工作。 (以上所有有效Q值)。祝你好運! – shellter

回答

1

有多種方法可以做到這一點,他們可以根據情況被認爲是「正確的」。

一種方式做到這一點在開機時可以使用AWS的情況下創建實例,你可以添加自定義的腳本時使用cloud-init,來進行測試:

enter image description here

這將使running commands on launch of your instance,如果你想這個過程自動化(基礎設施比如代碼),如果由於某種原因你已經有實例和運行,只是要按需更新,但不使用SSH,你可以使用例如terraform

,你腠ld使用saltstack

談到「冪等」 Ansible可能也這樣做的一個很好的工具,從ansible glossary

的操作是冪等,如果一旦執行它的結果是完全一樣的結果無需任何干預行動即可重複執行。

有許多工具可以幫助您實現這一目標,唯一的辦法是找到更適合您的需求/場景的工具。

1

您正在尋找這樣的事情:在結束

if [[ "$(grep '/usr/bin/certbot' /var/spool/cron/crontabs/$(whoami))" = "" ]] 
then 
    echo "15 3 * * * /usr/bin/certbot renew --quiet" >> /var/spool/cron/crontabs/$(whoami) 
fi 

和FI

你也能避免這樣做,很多須藤通過連接它們像:

sudo bash -c 'add-apt-repository -y ppa:certbot/certbot;apt-get update;apt-get upgrade -y;apt-get install -y software-properties-common python-certbot-nginx nginx;sed -i "s/server_name .*;/server_name $2;/" /etc/nginx/sites-available/default;systemctl restart nginx.service' 
1

如果你用sudo做這個,你以root身份做這個

這是imple事情在ansible做,做到最好有

做cron作業做這樣的:

CRON_FILE = 「/等/ cron.d/certbot」

如果[! -f $ CRON_FILE];然後

呼應'15 3 * * *的/ usr/bin中/ certbot更新--quiet」> $ CRON_FILE

網絡

2

我有這到目前爲止,但我錯過了幾個像獲得cron工作腳本的東西。

這裏完成的一種方式(正確),你開始什麼:

if ! sudo crontab -l | grep certbot; then 
    echo "15 3 * * * /usr/bin/certbot renew --quiet" | sudo tee -a /var/spool/cron/crontabs/root >/dev/null 
fi 

這裏的另一種方式,我喜歡,因爲它並不需要知道的crontab的路徑:

if ! sudo crontab -l | grep certbot; then 
    sudo crontab -l | { cat; echo "15 3 * * * /usr/bin/certbot renew --quiet"; } | sudo crontab - 
fi 

我看到缺少的東西是如何創建證書文件/etc/letsencrypt/live/$domain/fullchain.pem。 您是否以其他方式提供該服務? 或您需要該部分的幫助嗎?

不想以root身份執行此操作。

大部分的步驟包括運行apt-get, 以及您已經要求根。 也許你的意思是說你不想使用root來進行更新。 某些服務以專用用戶身份運行,而不是根用戶, ,但通過documentation of certbot查看,我還沒有看到類似的東西。 因此,似乎通常的做法是使用root進行續訂, 因此將更新命令添加到root的crontab對我來說似乎很好。

我會提高几件事情在腳本,使其更加強勁:

  • 的位置參數$1$2等散落很容易丟失的軌道,這可能導致錯誤。我會給他們適當的名字。

  • 命令行參數驗證if [ -z "$3" ]很弱,我會讓它更加嚴格,如if [ $# != 3 ]

  • 一旦生成了遠程腳本,就可以用bash -e來調用它,這對維護起到了很好的作用。但是如果腳本被其他沒有-e的東西調用,那麼保護就不會在那裏。與set -e一起構建腳本本身會更好。我會走得更遠,並使用更嚴格的set -euo pipefail。我也會把它放在外部腳本中。

  • 遠程腳本中的大多數命令都需要sudo。有一件事寫得很乏味。另一方面,如果一個命令結束花費很長時間以至於會話過期,則可能需要再次輸入root密碼,這會很煩人,特別是如果你走出去喝咖啡休息時間的話。最好通過在執行用戶的uid上添加一個檢查來始終以root身份運行。

  • 由於您使用bash -x ~/wks ...而不是~/wks運行遠程腳本,因此無需使用chmod使其可執行,以便可以刪除該步驟。

把上述在一起(然後一些),我會寫這樣的:

#!/bin/bash 

set -euo pipefail 

if [ $# != 3 ]; then 
    echo "Usage: $0 <server-ssh-address> <ssl-admin-email> <ssl-domain>" 
    echo "Example: singledomaincertnginx.sh [email protected] [email protected] some-sub-domain.mydomain.com" 
    exit 1 
fi 

remote=$1 
email=$2 
domain=$3 

remote_script_path=./wks 

ssh $remote "cat > $remote_script_path" << 'EOF' 
#!/bin/bash 

set -euo pipefail 

if [[ "$(id -u)" != 0 ]]; then 
    echo "This script must be run as root. (sudo $0)" 
    exit 1 
fi 

email=$1 
domain=$2 

echo email: $email 
echo domain: $domain 

add-apt-repository -y ppa:certbot/certbot 
apt-get update 
apt-get upgrade -y 
apt-get install -y software-properties-common 
apt-get install -y python-certbot-nginx 
apt-get install -y nginx 
sed -i "s/server_name .*;/server_name $domain;/" /etc/nginx/sites-available/default 
systemctl restart nginx.service 
#service nginx restart 

if [[ -e /etc/letsencrypt/live/$domain/fullchain.pem ]]; then 
    certbot -n --nginx --agree-tos -m $email -d $domain 
fi 

if ! crontab -l | grep -q certbot; then 
    crontab -l | { 
     cat 
     echo 
     echo "15 3 * * * /usr/bin/certbot renew --quiet" 
     echo 
    } | crontab - 
fi 
EOF 

ssh -t $remote "sudo bash -x $remote_script_path $email $domain" 
相關問題