Heroku 使用教程

Heroku平臺


Heroku平臺的靈活性極高且支持多種編程語言。若想把程序部署到Heroku上,開發(fā)者要使用Git把程序推送到HerokuGit服務(wù)器上。在服務(wù)器上,git push命令會自動觸發(fā)安裝、配置和部署程序。

Heroku使用名為Dyno的計(jì)算單元衡量用量,并以此為依據(jù)收取服務(wù)費(fèi)用。最常用的Dyno類型是Web Dyno,表示一個Web服務(wù)器實(shí)例。程序可以通過使用更多的Web Dyno以增強(qiáng)其請求處理能力。另一種Dyno類型是Worker Dyno,用來執(zhí)行后臺作業(yè)或其他輔助任務(wù)。

Heroku提供了大量的插件和擴(kuò)展,可用于數(shù)據(jù)庫、電子郵件支持和其他很多服務(wù)。

準(zhǔn)備程序


若想使用 Heroku,程序必須托管在 Git 倉庫中。如果你的程序托管在像 GitHub 或 BitBucket 這樣的遠(yuǎn)程 Git 服務(wù)器上,那么在本地 clone 程序后會創(chuàng)建一個本地 Git 倉庫,可無縫用于 Heroku。如果你的程序沒有托管在 Git 倉庫中,那么必須在開發(fā)電腦上創(chuàng)建一個倉庫。

注冊Heroku賬戶


heroku 官網(wǎng)

安裝Heroku Toolbelt


Heroku Toolbelt

Heroku Toolbelt是用于創(chuàng)建、管理Herokuapps的命令行工具

heroku 的命令行客戶端將被安裝到/usr/local/heroku,同時(shí),/usr/local/heroku/bin將被添加到你的PATH環(huán)境變量

下載并安裝完成后,在 shell 中輸入heroku login,用創(chuàng)建heroku賬號的email密碼登陸

$ heroku login
Enter your Heroku credentials.
Email: adam@example.com
Password (typing will be hidden):
Authentication successful.

把你的 SSH 公鑰上傳到 Heroku,這一點(diǎn)很重要,上傳后才能使用 git push 命令。正常情況下,login 命令會自動創(chuàng)建并上傳 SSH 公鑰。

創(chuàng)建程序


首先要確保程序在 Git 源碼控制系統(tǒng)中,然后在程序的頂級目錄下運(yùn)行創(chuàng)建命令

在 Heroku 創(chuàng)建一個 app, 以便 Heroku 準(zhǔn)備好接收你的代碼

當(dāng)你創(chuàng)建一個 app, 將創(chuàng)建并關(guān)聯(lián)一個名為heroku的遠(yuǎn)端到你的本地倉庫

apps:create [NAME] # create a new app 名稱必須以字母開始,只能包含小寫字母,數(shù)字和連字符, 而且名稱在 heroku 的所有程序中必須是唯一的

?  flask_blog git:(rest) ? heroku apps:create flask-blog-chaonet
Creating flask-blog-chaonet... done, stack is cedar-14
https://flask-blog-chaonet.herokuapp.com/ | https://git.heroku.com/flask-blog-chaonet.git
Git remote heroku added

查看已創(chuàng)建的 app

?  flask_blog git:(rest) ? heroku apps
=== My Apps
flask-blog-chaonet

默認(rèn) Heroku 會為你的 app 生成一個隨機(jī)的名字, 或者 你可以通過可選參數(shù)指定你的 app名。

現(xiàn)在,你可以向 Heroku 部署你的代碼了

$ git push heroku master # 必須將 本地 的 master push 到 heroku 的 master

應(yīng)用現(xiàn)在已經(jīng)部署了,確保至少一個 app 的實(shí)例正在運(yùn)行:

$ heroku ps:scale web=1

現(xiàn)在,可以用創(chuàng)建的包含 app 名稱的 URL 訪問 app. 有一個便捷的方法, 你可以像這樣打開web站點(diǎn):

$ heroku open

配置數(shù)據(jù)庫


Heroku 以擴(kuò)展形式支持 Postgres 數(shù)據(jù)庫。少于 1 萬條記錄、同時(shí)連接數(shù) 20 、沒有緩存 、不允許fork/follow、沒有 Postgres 日志 的小型數(shù)據(jù)庫無需付費(fèi)即可添加 到程序中。

官網(wǎng)教程: heroku-postgresql

添加 Postgres 到 Heroku 應(yīng)用

通過命令行,將 Heroku Postgres 添加到一個 Heroku 應(yīng)用:

?  flask_blog git:(rest) ? heroku addons:create heroku-postgresql:hobby-dev
Creating postgresql-sinuous-8326... done, (free)
Adding postgresql-sinuous-8326 to flask-blog-chaonet... done
Setting DATABASE_URL and restarting flask-blog-chaonet... done, v3
Database has been created and is available
 ! This database is empty. If upgrading, you can transfer
 ! data from another database with pg:copy
Use `heroku addons:docs heroku-postgresql` to view documentation.

選擇正確的 Heroku Postgres 方案

heroku-postgresql 插件

最低等級的業(yè)余版本有兩種方案 hobby-dev 和 hobby-basic

一旦 Heroku Postgres 被添加,一個 DATABASE_URL 設(shè)置將在 app 配置中生效,并包含用于訪問新提供的 Heroku Postgres 服務(wù)的 URL 。

這可以使用 heroku config 命令確認(rèn):

?  flask_blog git:(rest) ? heroku config -s | grep DATABASE_URL
DATABASE_URL=postgres://bjtrukgnhvnban:T0_N_OWYVz6NnasUwOf0FxVscO@ec2-54-83-52-71.compute-1.amazonaws.com:5432/d44ph8k76dl0h0

amazonaws ?

  • 建立主數(shù)據(jù)庫

Heroku 中的每個程序都支持多個數(shù)據(jù)庫。Heroku 建議使用 DATABASE_URL 變量保存主用數(shù)據(jù)庫信息。在單個數(shù)據(jù)庫的情況下,新的數(shù)據(jù)庫已經(jīng)被指定到 DATABASE_URL 。

對于多個數(shù)據(jù)庫的情況,可以設(shè)置主用數(shù)據(jù)庫:

$ heroku pg:promote HEROKU_POSTGRESQL_RED
Promoting HEROKU_POSTGRESQL_RED_URL to DATABASE_URL... done

DATABASE_URL 環(huán)境變量的格式正是 SQLAlchemy 所需的。回想一下 config.py 腳本的內(nèi)容,如果 設(shè)定了 DATABASE_URL,就使用其中保存的值,所以現(xiàn)在程序可以自動連接到 Postgres 數(shù)據(jù)庫。

  • 查看數(shù)據(jù)庫使用信息
?  flask_blog git:(rest) ? heroku pg:info
=== DATABASE_URL
Plan:        Hobby-dev
Status:      Available
Connections: 0/20
PG Version:  9.4.5
Created:     2016-01-09 02:57 UTC
Data Size:   6.7 MB
Tables:      0
Rows:        0/10000 (In compliance)
Fork/Follow: Unsupported
Rollback:    Unsupported
Add-on:      postgresql-sinuous-8326

heroku 的命令行命令

在 MAC 中安裝 Postgres

推薦在本地開發(fā)環(huán)境與生產(chǎn)環(huán)境運(yùn)行相同的數(shù)據(jù)庫

使用Postgres.app,是在 Mac 下使用PostgreSQL的最簡單的方法

postgresapp下載Postgres.app
解壓后將Postgres移到應(yīng)用程序文件夾
雙擊,然后你的 MAC 中就有一個PostgreSQL服務(wù)器在運(yùn)行了

  • 使用 Postgres.app 的命令行工具

配置$PATH變量

?  psycopg2-2.6.1  which psql
psql not found
?  psycopg2-2.6.1  export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/latest/bin
?  psycopg2-2.6.1  which psql
/Applications/Postgres.app/Contents/Versions/latest/bin/psql

通過命令psql連接你的數(shù)據(jù)庫

?  psycopg2-2.6.1  psql -h localhost
psql (9.5.0)
Type "help" for help.

chao-# \q
?  psycopg2-2.6.1

Using Command Line Tools with Postgres.app

在本地安裝 Heroku Postgres

與 Python 對接

官網(wǎng)教程

?  psycopg2-2.6.1  pip install psycopg2
Collecting psycopg2
  Using cached psycopg2-2.6.1.tar.gz
Building wheels for collected packages: psycopg2
  Running setup.py bdist_wheel for psycopg2
  Stored in directory: /Users/chao/Library/Caches/pip/wheels/e2/9a/5e/7b620848bbc7cfb9084aafea077be11618c2b5067bd532f329
Successfully built psycopg2
Installing collected packages: psycopg2
Successfully installed psycopg2-2.6.1

遇到的問題:

沒有通過 postgres.app 安裝 Postgres,就安裝 psycopg2 ,結(jié)果報(bào)錯

  • pip 安裝
?  flask_blog git:(rest) ? pip install psycopg2
Collecting psycopg2
  Using cached psycopg2-2.6.1.tar.gz
    Complete output from command python setup.py egg_info:
    running egg_info
    creating pip-egg-info/psycopg2.egg-info
    writing pip-egg-info/psycopg2.egg-info/PKG-INFO
    writing top-level names to pip-egg-info/psycopg2.egg-info/top_level.txt
    writing dependency_links to pip-egg-info/psycopg2.egg-info/dependency_links.txt
    writing manifest file 'pip-egg-info/psycopg2.egg-info/SOURCES.txt'
    warning: manifest_maker: standard file '-c' not found

    Error: pg_config executable not found.

    Please add the directory containing pg_config to the PATH
    or specify the full executable path with the option:

        python setup.py build_ext --pg-config /path/to/pg_config build ...

    or with the pg_config option in 'setup.cfg'.

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /private/var/folders/36/tdbs35wx1sx4d6nm4hrmwy0h0000gn/T/pip-build-XR5kDF/psycopg2

  • 下載安裝包安裝
?  psycopg2-2.6.1  ls
AUTHORS     LICENSE     MANIFEST.in NEWS        README.rst  examples    psycopg     setup.cfg   tests
INSTALL     MANIFEST    Makefile    PKG-INFO    doc         lib         scripts     setup.py

?  psycopg2-2.6.1  python setup.py build
running build
running build_py
creating build
creating build/lib.macosx-10.6-intel-2.7
creating build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/__init__.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/_json.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/_range.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/errorcodes.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/extensions.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/extras.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/pool.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/psycopg1.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
copying lib/tz.py -> build/lib.macosx-10.6-intel-2.7/psycopg2
creating build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/__init__.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/dbapi20.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/dbapi20_tpc.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_async.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_bug_gc.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_bugX000.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_cancel.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_connection.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_copy.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_cursor.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_dates.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_extras_dictcursor.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_green.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_lobject.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_module.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_notify.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_psycopg2_dbapi20.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_quote.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_transaction.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_types_basic.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_types_extras.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/test_with.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/testconfig.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
copying tests/testutils.py -> build/lib.macosx-10.6-intel-2.7/psycopg2/tests
running build_ext
Error: pg_config executable not found.

Please add the directory containing pg_config to the PATH
or specify the full executable path with the option:

    python setup.py build_ext --pg-config /path/to/pg_config build ...

or with the pg_config option in 'setup.cfg'.
?  psycopg2-2.6.1

配置 Python 用于 Postgres.app

在 Flask 中使用 Flask-SQLAlchemy 擴(kuò)展時(shí),可以直接在配置中定義,并由 app 讀取。

Postgres.app 的配置文檔

配置日志


任何寫到 標(biāo)準(zhǔn)輸出(stdout) 或標(biāo)準(zhǔn)錯誤(stderr) 的信息才會被 Heroku 抓取到日志,并在 Heroku 客戶端通過heroku logs命令查看。

config.py

        # 輸出到 stderr,以便被 Heroku 抓取到 logs
        import logging
        from logging import StreamHandler
        file_handler = StreamHandler()
        file_handler.setLevel(logging.WARNING)
        app.logger.addHandler(file_handler)

定義配置變量


Heroku 可以讓你在程序外部配置變量 —— 存儲類似加密密鑰外部資源地址的數(shù)據(jù)。

在運(yùn)行時(shí), 配置的變量被當(dāng)做環(huán)境變量暴露給應(yīng)用。

變量可以用Heroku的命令行工具配置,也可以在應(yīng)用的Dashboard頁面的settings頁簽下配置。

官網(wǎng)資料

配置電子郵件


Heroku 沒有提供 SMTP 服務(wù)器,所以我們要配置一個外部服務(wù)器。很多第三方擴(kuò)展能把 適用于生產(chǎn)環(huán)境的郵件發(fā)送服務(wù)集成到 Heroku 中,但對于測試和評估而言,使用繼承自 Config 基類的 mail 配置已經(jīng)足夠了。

由于直接把安全密令寫入腳本存在安全隱患,所以我們把訪問 mail SMTP服務(wù)器的用戶 名和密碼保存在環(huán)境變量中。

運(yùn)行生產(chǎn) Web 服務(wù)器


Heroku 沒有為托管程序提供 Web 服務(wù)器,相反,它希望程序啟動自己的服務(wù)器并監(jiān)聽環(huán) 境變量 PORT 中設(shè)定的端口。

Flask 自帶的開發(fā) Web 服務(wù)器表現(xiàn)很差,因?yàn)樗皇菫樯a(chǎn)環(huán)境設(shè)計(jì)的服務(wù)器。有兩個 可以在生產(chǎn)環(huán)境中使用、性能良好且支持 Flask 程序的服務(wù)器,分別是GunicornuWSGI

若想在本地測試 Heroku 配置,我們最好在虛擬環(huán)境中安裝 Web 服務(wù)器。例如,可通過如下命令安裝 Gunicorn:

(venv) $ pip install gunicorn

若要使用 Gunicorn 運(yùn)行程序,可執(zhí)行下面的命令:

     (venv) $ gunicorn manage:app
     2013-12-03 09:52:10 [14363] [INFO] Starting gunicorn 18.0
     2013-12-03 09:52:10 [14363] [INFO] Listening at: http://127.0.0.1:8000 (14363)
     2013-12-03 09:52:10 [14363] [INFO] Using worker: sync
     2013-12-03 09:52:10 [14368] [INFO] Booting worker with pid: 14368

manage:app 參數(shù)冒號左邊的部分表示定義程序的包或者模塊,冒號右邊的部分表示包中程序?qū)嵗拿?/code>。注意,Gunicor 默認(rèn)使用端口 8000,而 Flask 默認(rèn)使用 5000

添加依賴需求文件


Heroku 從程序頂級文件夾下的 requirements.txt 文件中加載包依賴。這個文件中的所有依賴都會在部署過程中導(dǎo)入 Heroku 創(chuàng)建的虛擬環(huán)境。

Heroku 的需求文件必須包含程序在生產(chǎn)環(huán)境中使用的所有通用依賴,以及支持 Postgres 數(shù)據(jù)庫的 psycopg2 包和 Gunicorn Web 服務(wù)器。

可以在需求文件中導(dǎo)入需求文件。

requirements.txt

     -r requirements/prod.txt
     gunicorn==18.0
     psycopg2==2.5.1

添加Procfile文件


Heroku 需要知道使用哪個命令啟動程序。命令在一個名為Procfile(沒有后綴)的特殊文件中指定。這個文件必須放在程序的頂級文件夾中。

web: gunicorn manage:app

Procfile文件內(nèi)容的格式很簡單:在每一行中指定一個任務(wù)名,后跟一個冒號,然后是執(zhí)行這個任務(wù)的命令。名為web的任務(wù)比較特殊任務(wù),Heroku 使用這個任務(wù)啟動 Web 服務(wù)器。

Heroku 會為這個任務(wù)提供一個PORT環(huán)境變量,用于設(shè)定程序監(jiān)聽請求的端口。如果設(shè)定了PORT變量, Gunicorn默認(rèn)就會使用其中保存的值,因此無需將其包含在啟動命令中。

部署程序后,Heroku 會運(yùn)行 Procfile 中列出的所有任務(wù)。

任務(wù)格式模板

程序可在 Procfile 中使用 web 之外的名字聲明其他任務(wù),例如程序所需的其他服務(wù)。

聲明任務(wù)類型的方式

使用 Heroku Local 進(jìn)行本地測試


官方教程

Heroku Local作為Heroku Toolbelt的一部分, 自動被安裝。

  • 在本地啟動所有在你的Profile中定義的任務(wù)

$ heroku local

heroku localheroku local:start的簡寫,作用相同

?  flask_blog git:(rest) ? heroku local
Downloading forego-0.16.1 to /Users/chao/.heroku... done
forego | starting web.1 on port 5000
web.1  | [2016-01-10 00:11:00 +0800] [17093] [INFO] Starting gunicorn 19.4.5
web.1  | [2016-01-10 00:11:00 +0800] [17093] [INFO] Listening at: http://0.0.0.0:5000 (17093)
web.1  | [2016-01-10 00:11:00 +0800] [17093] [INFO] Using worker: sync
web.1  | [2016-01-10 00:11:00 +0800] [17096] [INFO] Booting worker with pid: 17096

指定運(yùn)行的端口

?  flask_blog git:(rest) ? heroku local -p 8000
forego | starting web.1 on port 8000
web.1  | [2016-01-10 00:20:22 +0800] [17237] [INFO] Starting gunicorn 19.4.5
web.1  | [2016-01-10 00:20:22 +0800] [17237] [INFO] Listening at: http://0.0.0.0:8000 (17237)
web.1  | [2016-01-10 00:20:22 +0800] [17237] [INFO] Using worker: sync
web.1  | [2016-01-10 00:20:22 +0800] [17240] [INFO] Booting worker with pid: 17240
web.1  | [2016-01-10 00:21:11 +0800] [17237] [CRITICAL] WORKER TIMEOUT (pid:17240)
web.1  | [2016-01-10 00:21:11 +0800] [17240] [INFO] Worker exiting (pid: 17240)
web.1  | [2016-01-10 00:21:11 +0800] [17244] [INFO] Booting worker with pid: 17244

可以在本地指定運(yùn)行一個特定的進(jìn)程類型,例如webworker

$ heroku local web

然后,你就可以在本地測試 app。使用Ctrl+C停止

  • 設(shè)置本地環(huán)境變量

在本地運(yùn)行 APP,同樣需要輸入一系列 配置變量 作為 app 的配置。.env文件讓你可以收集 app 在本地運(yùn)行所需要的配置變量。當(dāng)使用heroku local命令運(yùn)行 APP,將會讀取.env文件,并且,每一個 名稱/值 對會被插入環(huán)境中,模仿實(shí)際的配置變量。

增加一個配置變量到你的.env文件:編輯.env文件,并在新的一行增加一個新name=value對。

由于.env文件中包含密碼和其他敏感的賬戶信息, 所以決不能將其添加到 Git 倉庫中,這個文件應(yīng)該只在存在于本地配置中。使用:echo .env >> .gitignore, 將.env文件列入 git 的忽略文件列表。

需要注意,你部署的生產(chǎn) app 可能使用到與本地開發(fā) app 不同的服務(wù)。例如,部署的生產(chǎn) app 可能有一個引用Heroku Postgres數(shù)據(jù)庫的DATABASE_URL配置變量,但你的本地 app可能在.env文件中有一個引用本地安裝的PostgresDATABASE_URL變量。

有時(shí)你可能想要在本地使用和 Heroku 環(huán)境相同的配置變量。對于每一個你想要添加到.env文件的配置變量,使用如下命令:

$ heroku config:get CONFIG-VAR-NAME -s >> .env

  • 查看環(huán)境變量

使用heroku config查看 app 的所有配置變量。使用cat .env查看.env文件的內(nèi)容

  • 另一個本地測試工具 Foreman

除了heroku local,原本的foreman也可以使用,但不再提供官方的支持,需要另外安裝。

Heroku Local has replaced Foreman in the Heroku Toolbelt

執(zhí)行 git push 命令部署


部署過程的最后一步是把程序上傳到 Heroku 服務(wù)器。在此之前,你要確保所有改動都已經(jīng)提交到本地Git倉庫,然后執(zhí)行git push heroku master把程序上傳到遠(yuǎn)程倉庫heroku

上傳代碼,中間遇到一個坑,一開始從本地的rest分支向herokumaster推送,報(bào)錯

?  flask_blog git:(rest) git push heroku master
Counting objects: 315, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (309/309), done.
Writing objects: 100% (315/315), 82.51 KiB | 0 bytes/s, done.
Total 315 (delta 190), reused 3 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote:
remote:  !     Push rejected, no Cedar-supported app detected
remote: HINT: This occurs when Heroku cannot detect the buildpack
remote:       to use for this application automatically.
remote: See https://devcenter.heroku.com/articles/buildpacks
remote:
remote: Verifying deploy....
remote:
remote: !   Push rejected to flask-blog-chaonet.
remote:
To https://git.heroku.com/flask-blog-chaonet.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/flask-blog-chaonet.git'

?  flask_blog git:(rest) heroku buildpacks:set heroku/python
Buildpack set. Next release on flask-blog-chaonet will use heroku/python.
Run git push heroku master to create a new release using this buildpack.

?  flask_blog git:(rest) git push heroku master
Counting objects: 315, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (309/309), done.
Writing objects: 100% (315/315), 82.56 KiB | 0 bytes/s, done.
Total 315 (delta 190), reused 3 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Using set buildpack heroku/python
remote:
remote:  !     Push rejected, failed to detect set buildpack heroku/python
remote: More info: https://devcenter.heroku.com/articles/buildpacks#detection-failure
remote:
remote: Verifying deploy....
remote:
remote: !   Push rejected to flask-blog-chaonet.
remote:
To https://git.heroku.com/flask-blog-chaonet.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/flask-blog-chaonet.git'

感覺可能是 分支名稱的問題,嘗試切換到 master,合并分支后再試

?  flask_blog git:(rest) git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

?  flask_blog git:(master) ? git merge rest
Updating 40d4e6e..90872cd
Fast-forward
 .gitignore                                      |   2 +
 Procfile                                        |   1 +
 app.db                                          | Bin 76800 -> 83968 bytes
 app/__init__.py                                 |  67 +++++----
 app/api_1_0/__init__.py                         |   5 +
 app/api_1_0/authentication.py                   |  59 ++++++++
 app/api_1_0/comments.py                         |  79 +++++++++++
 app/api_1_0/decorators.py                       |  21 +++
 app/api_1_0/errors.py                           |  21 +++
 app/api_1_0/posts.py                            |  74 ++++++++++
 app/api_1_0/users.py                            |  75 ++++++++++
 app/auth/__init__.py                            |   5 +
 app/auth/forms.py                               |  65 +++++++++
 app/auth/views.py                               | 196 ++++++++++++++++++++++++++
 app/email.py                                    |  11 ++
 app/exceptions.py                               |   4 +
 app/main/__init__.py                            |  13 ++
 app/main/error.py                               |  12 ++
 app/main/forms.py                               |  69 ++++++++++
 app/main/views.py                               | 401 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 app/models.py                                   |  71 +++++++++-
 app/templates/_comments.html                    |  10 +-
 app/templates/_posts.html                       |  12 +-
 app/templates/{ => auth/email}/confirm.html     |   2 +-
 app/templates/auth/email/confirm.txt            |   6 +
 app/templates/{ => auth/email}/confirmmail.html |   2 +-
 app/templates/{ => auth/email}/confirmmail.txt  |   2 +-
 app/templates/{ => auth}/login.html             |   4 +-
 app/templates/{ => auth}/register.html          |   0
 app/templates/{ => auth}/renew.html             |   0
 app/templates/{ => auth}/unconfirmed.html       |   2 +-
 app/templates/base.html                         |  14 +-
 app/templates/changepassword.html               |   2 +-
 app/templates/changepassword.txt                |   2 +-
 app/templates/confirm.txt                       |   6 -
 app/templates/followers.html                    |   2 +-
 app/templates/{ => main}/index.html             |   6 +-
 app/templates/main/moderate.html                |  16 +++
 app/templates/user.html                         |  14 +-
 app/views.py                                    |   1 -
 app_pro.db                                      |   0
 app_test.db                                     | Bin 0 -> 24576 bytes
 config.py                                       | 130 +++++++++++++----
 requirements.txt                                |  43 ++++++
 run.py                                          | 114 ++++++++++++++-
 test/test_api.py                                |  71 ++++++++++
 test/test_basics.py                             |  24 ++++
 test/test_client.py                             |  86 ++++++++++++
 test/test_selenium.py                           |  90 ++++++++++++
 test/test_user_model.py                         |  45 +++++-
 tmp/coverage/app___init___py.html               | 195 ++++++++++++++++++++++++++
 tmp/coverage/app_api_1_0_authentication_py.html | 209 ++++++++++++++++++++++++++++
 tmp/coverage/app_api_1_0_comments_py.html       | 249 +++++++++++++++++++++++++++++++++
 tmp/coverage/app_api_1_0_decorators_py.html     | 133 ++++++++++++++++++
 tmp/coverage/app_api_1_0_errors_py.html         | 133 ++++++++++++++++++
 tmp/coverage/app_api_1_0_posts_py.html          | 239 ++++++++++++++++++++++++++++++++
 tmp/coverage/app_api_1_0_users_py.html          | 241 ++++++++++++++++++++++++++++++++
 tmp/coverage/app_auth_forms_py.html             | 221 +++++++++++++++++++++++++++++
 tmp/coverage/app_auth_views_py.html             | 483 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tmp/coverage/app_email_py.html                  | 113 +++++++++++++++
 tmp/coverage/app_main___init___py.html          | 117 ++++++++++++++++
 tmp/coverage/app_main_views_py.html             | 823 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tmp/coverage/app_models_py.html                 | 981 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tmp/coverage/coverage_html.js                   | 512 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tmp/coverage/index.html                         | 260 ++++++++++++++++++++++++++++++++++
 tmp/coverage/jquery.debounce.min.js             |   9 ++
 tmp/coverage/jquery.hotkeys.js                  |  99 +++++++++++++
 tmp/coverage/jquery.isonscreen.js               |  53 +++++++
 tmp/coverage/jquery.min.js                      |   4 +
 tmp/coverage/jquery.tablesorter.min.js          |   2 +
 tmp/coverage/keybd_closed.png                   | Bin 0 -> 264 bytes
 tmp/coverage/keybd_open.png                     | Bin 0 -> 267 bytes
 tmp/coverage/status.json                        |   1 +
 tmp/coverage/style.css                          | 326 +++++++++++++++++++++++++++++++++++++++++++
 74 files changed, 7248 insertions(+), 112 deletions(-)
 create mode 100644 Procfile
 create mode 100644 app/api_1_0/__init__.py
 create mode 100644 app/api_1_0/authentication.py
 create mode 100644 app/api_1_0/comments.py
 create mode 100644 app/api_1_0/decorators.py
 create mode 100644 app/api_1_0/errors.py
 create mode 100644 app/api_1_0/posts.py
 create mode 100644 app/api_1_0/users.py
 create mode 100644 app/auth/__init__.py
 create mode 100644 app/auth/forms.py
 create mode 100644 app/auth/views.py
 create mode 100644 app/email.py
 create mode 100644 app/exceptions.py
 create mode 100644 app/main/__init__.py
 create mode 100644 app/main/error.py
 create mode 100644 app/main/forms.py
 create mode 100644 app/main/views.py
 rename app/templates/{ => auth/email}/confirm.html (75%)
 create mode 100644 app/templates/auth/email/confirm.txt
 rename app/templates/{ => auth/email}/confirmmail.html (74%)
 rename app/templates/{ => auth/email}/confirmmail.txt (50%)
 rename app/templates/{ => auth}/login.html (71%)
 rename app/templates/{ => auth}/register.html (100%)
 rename app/templates/{ => auth}/renew.html (100%)
 rename app/templates/{ => auth}/unconfirmed.html (80%)
 delete mode 100644 app/templates/confirm.txt
 rename app/templates/{ => main}/index.html (81%)
 create mode 100644 app/templates/main/moderate.html
 create mode 100644 app_pro.db
 create mode 100644 app_test.db
 create mode 100644 requirements.txt
 create mode 100644 test/test_api.py
 create mode 100644 test/test_basics.py
 create mode 100644 test/test_client.py
 create mode 100644 test/test_selenium.py
 create mode 100644 tmp/coverage/app___init___py.html
 create mode 100644 tmp/coverage/app_api_1_0_authentication_py.html
 create mode 100644 tmp/coverage/app_api_1_0_comments_py.html
 create mode 100644 tmp/coverage/app_api_1_0_decorators_py.html
 create mode 100644 tmp/coverage/app_api_1_0_errors_py.html
 create mode 100644 tmp/coverage/app_api_1_0_posts_py.html
 create mode 100644 tmp/coverage/app_api_1_0_users_py.html
 create mode 100644 tmp/coverage/app_auth_forms_py.html
 create mode 100644 tmp/coverage/app_auth_views_py.html
 create mode 100644 tmp/coverage/app_email_py.html
 create mode 100644 tmp/coverage/app_main___init___py.html
 create mode 100644 tmp/coverage/app_main_views_py.html
 create mode 100644 tmp/coverage/app_models_py.html
 create mode 100644 tmp/coverage/coverage_html.js
 create mode 100644 tmp/coverage/index.html
 create mode 100644 tmp/coverage/jquery.debounce.min.js
 create mode 100644 tmp/coverage/jquery.hotkeys.js
 create mode 100644 tmp/coverage/jquery.isonscreen.js
 create mode 100644 tmp/coverage/jquery.min.js
 create mode 100644 tmp/coverage/jquery.tablesorter.min.js
 create mode 100644 tmp/coverage/keybd_closed.png
 create mode 100644 tmp/coverage/keybd_open.png
 create mode 100644 tmp/coverage/status.json
 create mode 100644 tmp/coverage/style.css

?  flask_blog git:(master) git push heroku master
Counting objects: 491, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (482/482), done.
Writing objects: 100% (491/491), 232.17 KiB | 0 bytes/s, done.
Total 491 (delta 301), reused 2 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Using set buildpack heroku/python
remote: -----> Python app detected
remote: -----> Installing runtime (python-2.7.11)
remote: -----> Installing dependencies with pip
remote:        Collecting alembic==0.8.4 (from -r requirements.txt (line 1))
remote:        Downloading alembic-0.8.4.tar.gz (950kB)
remote:        Collecting bleach==1.4.2 (from -r requirements.txt (line 2))
remote:        Downloading bleach-1.4.2-py2.py3-none-any.whl
remote:        Collecting blinker==1.4 (from -r requirements.txt (line 3))
remote:        Downloading blinker-1.4.tar.gz (111kB)
remote:        Collecting coverage==4.0.3 (from -r requirements.txt (line 4))
remote:        Downloading coverage-4.0.3.tar.gz (354kB)
remote:        Collecting decorator==4.0.6 (from -r requirements.txt (line 5))
remote:        Downloading decorator-4.0.6-py2.py3-none-any.whl
remote:        Collecting dominate==2.1.16 (from -r requirements.txt (line 6))
remote:        Downloading dominate-2.1.16.zip
remote:        Collecting Flask==0.10.1 (from -r requirements.txt (line 7))
remote:        Downloading Flask-0.10.1.tar.gz (544kB)
remote:        Collecting Flask-Bootstrap==3.3.5.7 (from -r requirements.txt (line 8))
remote:        Downloading Flask-Bootstrap-3.3.5.7.tar.gz (451kB)
remote:        Collecting Flask-HTTPAuth==2.7.0 (from -r requirements.txt (line 9))
remote:        Downloading Flask-HTTPAuth-2.7.0.tar.gz
remote:        Collecting Flask-Login==0.3.2 (from -r requirements.txt (line 10))
remote:        Downloading Flask-Login-0.3.2.tar.gz
remote:        Collecting Flask-Mail==0.9.1 (from -r requirements.txt (line 11))
remote:        Downloading Flask-Mail-0.9.1.tar.gz (45kB)
remote:        Collecting Flask-Markdown==0.3 (from -r requirements.txt (line 12))
remote:        Downloading Flask-Markdown-0.3.tar.gz (165kB)
remote:        Collecting Flask-Migrate==1.6.0 (from -r requirements.txt (line 13))
remote:        Downloading Flask-Migrate-1.6.0.tar.gz
remote:        Collecting Flask-Moment==0.5.1 (from -r requirements.txt (line 14))
remote:        Downloading Flask-Moment-0.5.1.tar.gz
remote:        Collecting Flask-PageDown==0.2.1 (from -r requirements.txt (line 15))
remote:        Downloading Flask-PageDown-0.2.1.tar.gz
remote:        Collecting Flask-Script==2.0.5 (from -r requirements.txt (line 16))
remote:        Downloading Flask-Script-2.0.5.tar.gz (42kB)
remote:        Collecting Flask-SQLAlchemy==2.1 (from -r requirements.txt (line 17))
remote:        Downloading Flask-SQLAlchemy-2.1.tar.gz (95kB)
remote:        Collecting Flask-SSLify==0.1.5 (from -r requirements.txt (line 18))
remote:        Downloading Flask-SSLify-0.1.5.tar.gz
remote:        Collecting Flask-WTF==0.12 (from -r requirements.txt (line 19))
remote:        Downloading Flask_WTF-0.12-py2-none-any.whl
remote:        Collecting ForgeryPy==0.1 (from -r requirements.txt (line 20))
remote:        Downloading ForgeryPy-0.1.tar.gz
remote:        Collecting gunicorn==19.4.5 (from -r requirements.txt (line 21))
remote:        Downloading gunicorn-19.4.5-py2.py3-none-any.whl (112kB)
remote:        Collecting html5lib==0.9999999 (from -r requirements.txt (line 22))
remote:        Downloading html5lib-0.9999999.tar.gz (889kB)
remote:        Collecting httpie==0.9.3 (from -r requirements.txt (line 23))
remote:        Downloading httpie-0.9.3-py2.py3-none-any.whl (66kB)
remote:        Collecting itsdangerous==0.24 (from -r requirements.txt (line 24))
remote:        Downloading itsdangerous-0.24.tar.gz (46kB)
remote:        Collecting Jinja2==2.8 (from -r requirements.txt (line 25))
remote:        Downloading Jinja2-2.8-py2.py3-none-any.whl (263kB)
remote:        Collecting Mako==1.0.3 (from -r requirements.txt (line 26))
remote:        Downloading Mako-1.0.3.tar.gz (565kB)
remote:        Collecting Markdown==2.6.5 (from -r requirements.txt (line 27))
remote:        Downloading Markdown-2.6.5.tar.gz (301kB)
remote:        Collecting MarkupSafe==0.23 (from -r requirements.txt (line 28))
remote:        Downloading MarkupSafe-0.23.tar.gz
remote:        Collecting pbr==1.8.1 (from -r requirements.txt (line 29))
remote:        Downloading pbr-1.8.1-py2.py3-none-any.whl (89kB)
remote:        Collecting psycopg2==2.6.1 (from -r requirements.txt (line 30))
remote:        Downloading psycopg2-2.6.1.tar.gz (371kB)
remote:        Collecting Pygments==2.0.2 (from -r requirements.txt (line 31))
remote:        Downloading Pygments-2.0.2-py2-none-any.whl (672kB)
remote:        Collecting python-editor==0.5 (from -r requirements.txt (line 32))
remote:        Downloading python-editor-0.5.tar.gz
remote:        Collecting requests==2.9.1 (from -r requirements.txt (line 33))
remote:        Downloading requests-2.9.1-py2.py3-none-any.whl (501kB)
remote:        Collecting selenium==2.48.0 (from -r requirements.txt (line 34))
remote:        Downloading selenium-2.48.0-py2-none-any.whl (872kB)
remote:        Collecting six==1.10.0 (from -r requirements.txt (line 35))
remote:        Downloading six-1.10.0-py2.py3-none-any.whl
remote:        Collecting SQLAlchemy==1.0.10 (from -r requirements.txt (line 36))
remote:        Downloading SQLAlchemy-1.0.10.tar.gz (4.7MB)
remote:        Collecting sqlalchemy-migrate==0.10.0 (from -r requirements.txt (line 37))
remote:        Downloading sqlalchemy_migrate-0.10.0-py2-none-any.whl (108kB)
remote:        Collecting sqlparse==0.1.18 (from -r requirements.txt (line 38))
remote:        Downloading sqlparse-0.1.18.tar.gz (58kB)
remote:        Collecting Tempita==0.5.2 (from -r requirements.txt (line 39))
remote:        Downloading Tempita-0.5.2.tar.gz
remote:        Collecting visitor==0.1.2 (from -r requirements.txt (line 40))
remote:        Downloading visitor-0.1.2.tar.gz
remote:        Collecting Werkzeug==0.11.2 (from -r requirements.txt (line 41))
remote:        Downloading Werkzeug-0.11.2-py2.py3-none-any.whl (304kB)
remote:        Collecting wheel==0.24.0 (from -r requirements.txt (line 42))
remote:        Downloading wheel-0.24.0-py2.py3-none-any.whl (63kB)
remote:        Collecting WTForms==2.0.2 (from -r requirements.txt (line 43))
remote:        Downloading WTForms-2.0.2-py27-none-any.whl (128kB)
remote:        Installing collected packages: SQLAlchemy, MarkupSafe, Mako, python-editor, alembic, six, html5lib, bleach, blinker, coverage, decorator, dominate, Werkzeug, Jinja2, itsdangerous, Flask, visitor, Flask-Bootstrap, Flask-HTTPAuth, Flask-Login, Flask-Mail, Markdown, Flask-Markdown, Flask-SQLAlchemy, Flask-Script, Flask-Migrate, Flask-Moment, WTForms, Flask-PageDown, Flask-SSLify, Flask-WTF, ForgeryPy, gunicorn, Pygments, requests, httpie, pbr, psycopg2, selenium, sqlparse, Tempita, sqlalchemy-migrate, wheel
remote:        Running setup.py install for SQLAlchemy
remote:        Running setup.py install for MarkupSafe
remote:        Running setup.py install for Mako
remote:        Running setup.py install for python-editor
remote:        Running setup.py install for alembic
remote:        Running setup.py install for html5lib
remote:        Running setup.py install for blinker
remote:        Running setup.py install for coverage
remote:        Running setup.py install for dominate
remote:        Running setup.py install for itsdangerous
remote:        Running setup.py install for Flask
remote:        Running setup.py install for visitor
remote:        Running setup.py install for Flask-Bootstrap
remote:        Running setup.py install for Flask-HTTPAuth
remote:        Running setup.py install for Flask-Login
remote:        Running setup.py install for Flask-Mail
remote:        Running setup.py install for Markdown
remote:        Running setup.py install for Flask-Markdown
remote:        Running setup.py install for Flask-SQLAlchemy
remote:        Running setup.py install for Flask-Script
remote:        Running setup.py install for Flask-Migrate
remote:        Running setup.py install for Flask-Moment
remote:        Running setup.py install for Flask-PageDown
remote:        Running setup.py install for Flask-SSLify
remote:        Running setup.py install for ForgeryPy
remote:        Running setup.py install for psycopg2
remote:        Running setup.py install for sqlparse
remote:        Running setup.py install for Tempita
remote:        Successfully installed Flask-0.10.1 Flask-Bootstrap-3.3.5.7 Flask-HTTPAuth-2.7.0 Flask-Login-0.3.2 Flask-Mail-0.9.1 Flask-Markdown-0.3 Flask-Migrate-1.6.0 Flask-Moment-0.5.1 Flask-PageDown-0.2.1 Flask-SQLAlchemy-2.1 Flask-SSLify-0.1.5 Flask-Script-2.0.5 Flask-WTF-0.12 ForgeryPy-0.1 Jinja2-2.8 Mako-1.0.3 Markdown-2.6.5 MarkupSafe-0.23 Pygments-2.0.2 SQLAlchemy-1.0.10 Tempita-0.5.2 WTForms-2.0.2 Werkzeug-0.11.2 alembic-0.8.4 bleach-1.4.2 blinker-1.4 coverage-4.0.3 decorator-4.0.6 dominate-2.1.16 gunicorn-19.4.5 html5lib-0.9999999 httpie-0.9.3 itsdangerous-0.24 pbr-1.8.1 psycopg2-2.6.1 python-editor-0.5 requests-2.9.1 selenium-2.48.0 six-1.10.0 sqlalchemy-migrate-0.10.0 sqlparse-0.1.18 visitor-0.1.2 wheel-0.24.0
remote:
remote:
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing... done, 44.6MB
remote: -----> Launching...
remote:        Released v7
remote:        https://flask-blog-chaonet.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/flask-blog-chaonet.git
 * [new branch]      master -> master

成功,按照requirements.txt安裝依賴的庫

建立運(yùn)行環(huán)境數(shù)據(jù)庫

?  flask_blog git:(master) heroku run python run.py deploy
Running python run.py deploy on flask-blog-chaonet... up, run.6723
/app/.heroku/python/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py:800: UserWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True to suppress this warning.
  warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True to suppress this warning.')
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> c1b387222189, empty message
INFO  [alembic.runtime.migration] Running upgrade c1b387222189 -> c4a4f802bdf4, empty message
INFO  [alembic.runtime.migration] Running upgrade c4a4f802bdf4 -> 83e0975c0db1, add role permission
INFO  [alembic.runtime.migration] Running upgrade 83e0975c0db1 -> ee9c55ba9b22, add user profile
INFO  [alembic.runtime.migration] Running upgrade ee9c55ba9b22 -> 431d275d6a70, add user.about_me
INFO  [alembic.runtime.migration] Running upgrade 431d275d6a70 -> d6f4efe3ffe1, add User.avatar_hash
INFO  [alembic.runtime.migration] Running upgrade d6f4efe3ffe1 -> ac6e9871c9a4, add Post ,relationship with User
INFO  [alembic.runtime.migration] Running upgrade ac6e9871c9a4 -> 6f219f6bca6e, add Post.on_changed_body, body_html, db.event.listen
INFO  [alembic.runtime.migration] Running upgrade 6f219f6bca6e -> 3aca4362a467, add Follow model, user.followers
                                                                                                                ollowed
INFO  [alembic.runtime.migration] Running upgrade 3aca4362a467 -> e3cfb10aeab6, add comment model

創(chuàng)建并配置好數(shù)據(jù)庫表之后就可以重啟程序了,直接使用下述命令即可:

     $ heroku restart
     Restarting dynos... done

至此,程序就完全部署好了,可通過 https://<appname>.hero-kuapp.com 訪問。

查看日志


不同類型的消息,會通過顏色區(qū)分顯示

?  flask_blog git:(master) heroku logs
...
2016-01-10T09:04:16.778460+00:00 heroku[run.6723]: Awaiting client
2016-01-10T09:04:16.871340+00:00 heroku[run.6723]: Starting process with command `python run.py deploy`
2016-01-10T09:04:17.236929+00:00 heroku[run.6723]: State changed from starting to up
2016-01-10T09:04:20.574974+00:00 heroku[run.6723]: State changed from up to complete
2016-01-10T09:04:20.567984+00:00 heroku[run.6723]: Process exited with status 0
2016-01-10T09:14:49.296965+00:00 heroku[web.1]: State changed from up to starting
2016-01-10T09:14:53.791001+00:00 heroku[web.1]: Starting process with command `gunicorn run:app`
2016-01-10T09:14:54.840605+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2016-01-10T09:14:56.154205+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [3] [INFO] Starting gunicorn 19.4.5
2016-01-10T09:14:56.230606+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [10] [INFO] Booting worker with pid: 10
2016-01-10T09:14:56.154848+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [3] [INFO] Listening at: http://0.0.0.0:10268 (3)
2016-01-10T09:14:56.154974+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [3] [INFO] Using worker: sync
2016-01-10T09:14:56.160120+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [9] [INFO] Booting worker with pid: 9
2016-01-10T09:14:56.476881+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [10] [INFO] Worker exiting (pid: 10)
2016-01-10T09:14:56.547413+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [3] [INFO] Shutting down: Master
2016-01-10T09:14:56.475915+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [9] [INFO] Worker exiting (pid: 9)
2016-01-10T09:14:56.529060+00:00 app[web.1]: [2016-01-10 09:14:56 +0000] [3] [INFO] Handling signal: term
2016-01-10T09:14:56.954815+00:00 app[web.1]: /app/.heroku/python/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py:800: UserWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True to suppress this warning.
2016-01-10T09:14:56.954818+00:00 app[web.1]:   warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True to suppress this warning.')
2016-01-10T09:14:57.283202+00:00 app[web.1]:   warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True to suppress this warning.')
2016-01-10T09:14:57.283198+00:00 app[web.1]: /app/.heroku/python/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py:800: UserWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True to suppress this warning.
2016-01-10T09:14:57.480937+00:00 heroku[web.1]: State changed from starting to up
2016-01-10T09:14:57.513335+00:00 heroku[web.1]: Process exited with status 0
2016-01-10T09:15:06.569626+00:00 heroku[router]: at=info method=GET path="/" host=flask-blog-chaonet.herokuapp.com request_id=32f4cf3a-d766-441b-bbe1-0e7052a37209 fwd="107.161.27.197" dyno=web.1 connect=0ms service=291ms status=200 bytes=3417
2016-01-10T09:15:09.079151+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=flask-blog-chaonet.herokuapp.com request_id=4e065440-cb19-420a-834e-8e4d8e4c956c fwd="107.161.27.197" dyno=web.1 connect=1ms service=19ms status=404 bytes=655
2016-01-10T09:15:16.012079+00:00 heroku[router]: at=info method=GET path="/" host=flask-blog-chaonet.herokuapp.com request_id=ac1e63ac-0133-4cad-adac-66563437c70c fwd="107.161.27.197" dyno=web.1 connect=0ms service=506ms status=200 bytes=3504
2016-01-10T09:15:17.703574+00:00 heroku[router]: at=info method=GET path="/followed" host=flask-blog-chaonet.herokuapp.com request_id=0fc98138-ca6f-4873-8327-4a22f892d432 fwd="107.161.27.197" dyno=web.1 connect=1ms service=13ms status=302 bytes=875
2016-01-10T09:15:18.327896+00:00 heroku[router]: at=info method=GET path="/auth/login?next=%2Ffollowed" host=flask-blog-chaonet.herokuapp.com request_id=8d44ff19-c673-4e61-929e-d6ce89678b3a fwd="107.161.27.197" dyno=web.1 connect=0ms service=25ms status=200 bytes=4071
2016-01-10T09:15:19.085786+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=flask-blog-chaonet.herokuapp.com request_id=d327a6e7-f26b-4514-8813-c2af94dfd639 fwd="107.161.27.197" dyno=web.1 connect=0ms service=3ms status=404 bytes=655
2016-01-10T09:15:20.795897+00:00 heroku[router]: at=info method=GET path="/" host=flask-blog-chaonet.herokuapp.com request_id=de598303-d092-4647-8758-9e050d089f2e fwd="107.161.27.197" dyno=web.1 connect=2ms service=23ms status=200 bytes=3504
2016-01-10T09:15:22.840818+00:00 heroku[router]: at=info method=GET path="/auth/login" host=flask-blog-chaonet.herokuapp.com request_id=db4a579c-d80b-4205-963e-53d4f8aeb4a3 fwd="107.161.27.197" dyno=web.1 connect=2ms service=9ms status=200 bytes=4014
2016-01-10T09:15:25.834388+00:00 heroku[router]: at=info method=GET path="/auth/register" host=flask-blog-chaonet.herokuapp.com request_id=32a0d112-6dfa-4c8b-bd25-2bf0296add0d fwd="107.161.27.197" dyno=web.1 connect=2ms service=31ms status=200 bytes=4084
2016-01-10T09:15:28.548938+00:00 heroku[router]: at=info method=GET path="/" host=flask-blog-chaonet.herokuapp.com request_id=0f731062-0cfe-4e51-8967-13ab87ef03c5 fwd="107.161.27.197" dyno=web.1 connect=2ms service=15ms status=200 bytes=3504

應(yīng)用程序維護(hù)模式


維護(hù)時(shí)可以設(shè)置顯示維護(hù)信息

?  flask_blog git:(master) heroku maintenance -h
Usage: heroku maintenance

display the current maintenance status of app

 -a, --app APP       # app to run command against
 -r, --remote REMOTE # git remote of app to run command against

Additional commands, type "heroku help COMMAND" for more details:

  maintenance:off  #  take the app out of maintenance mode
  maintenance:on   #  put the app into maintenance mode

開啟顯示維護(hù)信息

?  flask_blog git:(master) heroku maintenance:on
Enabling maintenance mode for flask-blog-chaonet... done

頁面顯示的內(nèi)容

Application Offline for Maintenance
This application is undergoing maintenance right now. Please check back later.

維護(hù)結(jié)束后,重新開啟應(yīng)用,正常訪問

?  flask_blog git:(master) heroku maintenance:off
Disabling maintenance mode for flask-blog-chaonet... done
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,619評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,155評論 3 425
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,635評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,539評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,255評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,646評論 1 326
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,655評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,838評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,399評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,146評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,338評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,893評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,565評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,983評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,257評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,059評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,296評論 2 376

推薦閱讀更多精彩內(nèi)容