Skip to content

zh

使用Apache虛擬主機和Python虛擬環境設置Django服務器

花了我一些時間才使所有東西都能一起工作,所以我想把步驟記錄下來,以節省你未來的時間。

首先,假設你已經有你的CentOS/Ubuntu實例正在運行,並且已安裝Python。創建一個專案資料夾並設定適當的權限:

    sudo mkdir /opt/yourpath/projects
    sudo chown $USER /opt/yourpath/projects

如果你還沒有初始化你的專案,你可以這樣做:

    python -m pip install Django
    django-admin startproject APPNAME /opt/yourpath/projects/APPNAME

默認情況下,服務器運行在8000端口:

    python manage.py runserver

為了準備你的Django服務器進入生產模式,編輯settings.py文件,使用以下設置:

    DEBUG = False
    ALLOWED_HOSTS = ['*']
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'static')

然後,你可以使用下面的命令構建靜態文件:

    python manage.py collectstatic --noinput

接下來,通過Apache網絡服務器來提供你的web應用程式。假設你透過yum或apt-get安裝了Apache2,為你的專案啟用虛擬主機,並創建以下文件:

    touch /opt/yourpath/apache2/conf/vhosts/project-vhost.conf

在下面填入内容:

    <IfDefine !IS_APPNAME_LOADED>
      Define IS_APPNAME_LOADED
      WSGIDaemonProcess APPNAME python-home=/opt/yourpath/python python-path=/opt/yourpath/projects/APPNAME
    </IfDefine>
    <VirtualHost 127.0.0.1:80 _default_:80>
    ...

記住要用你的Django專案名稱替換所有的APPNAME。然後,為HTTPS創建另一個文件:

    touch /opt/yourpath/apache2/conf/vhosts/project-https-vhost.conf

並用相似的內容填充它,適當替換APPNAME。

更新配置後,重新啟動Apache服務器。你的Django站點現在應該已經可以運行了。

最後,在虛擬環境內隔離Python依賴,以避免依賴問題和版本衝突。在你的專案目錄裡,運行:

    pip install virtualenv
    virtualenv venv
    source venv/bin/activate

這會創建一個包含所有Python可執行文件的資料夾。後續的pip install命令只會影響這個資料夾。現在,回去編輯project-vhost.confproject-https-vhost.conf,將 python-home路徑改為指向venv資料夾:

由:

    WSGIDaemonProcess APPNAME python-home=/opt/yourpath/python python-path=/opt/yourpath/projects/APPNAME

變為:

    WSGIDaemonProcess APPNAME python-home=/opt/yourpath/projects/APPNAME/venv python-path=/opt/yourpath/projects/APPNAME

一定要將Python home路徑指向venv資料夾,而不是/bin可執行檔或Python位置,以避免出現500錯誤。如果你遇到問題,請檢查Apache服務器的錯誤日誌:

    tail /opt/yourpath/apache2/logs/error_log

就這樣!在你的公開IP地址上導航,你應該能看到你的Django頁面。

附註:如果你在WSGI層面遇到超時錯誤:

    Timeout when reading response headers from daemon process

編輯project-vhost.confproject-https-vhost.conf,在WSGIDaemonProcess下面添加以下行:

    WSGIApplicationGroup %{GLOBAL}

這種增加可以解決由Python C擴展模組(如NumPy)導致的超時。

不要為所有事情下載應用程式

應用程式越來越無關緊要。 當瀏覽器可以作為足夠的替代品時,就不需要下載無效的軟件。 使用應用程式的主要好處是數據收集和廣告服務,這有利於科技巨頭而不是終端用戶。

一個能幹的程序員會花時間淬煉他們的工作。他們構建測試案例,將複雜的問題簡化為較小的任務,並對手頭的主題進行深思熟慮。相比之下,技能較差的開發人員往往缺乏實現任何重大成就的意願或才能。作為用戶,很難確定哪個應用程式更優越。

當開發人員犯錯時,後果通常是次要的。最壞的情況下,他們可能會在應用商店上獲得差評。在更嚴重的情況下,管理層可能會追究他們的責任。但是,大多數情況下,沒有持久的後果。有些開發人員可能會修補這些缺陷,而其他人可能會引入新的缺陷。您不進行全面的回歸測試就無法知道。

問題不僅僅在於差劣的開發者;即使是有才華的人也發現自己陷入了一個日益非理性的行業。這些技能優秀的程序員往往沒有時間來明確要求或進行 gronding 的計劃。此外,他們承受著不斷推出新功能的巨大壓力,特別是自從最新的 iPhone 發布以來。許多公司希望他們的開發人員能每天產出多個新功能以增加應用程式的下載量,但這種節奏對於保持質量來說是無法持續的。

創建經過充分測試,堅固的軟件以處理所有可能的狀態本身就是一項挑戰。這更加困難,因為來自 Slack 消息和進度報告會議的持續干擾。通常,公司會雇用經驗豐富的全棧工程師來完成工作,卻發現這成本過高。

用戶大多並未意識到這些挑戰。受到 spaghetti 代碼和無數缺陷的困擾,軟件開發人員變得不滿或悲觀,甚至兩者兼而有之。難怪許多人轉行成為項目管理角色,這提供了較少的壓力,更高的收入和更可預見的工作時間。他們不再致力於通過更好的軟件改變世界。

這種失功能的軟件工程文化的責任並不完全在於公司。像 Apple、Google、Facebook 和 Amazon 這樣的科技巨頭塑造了我們做生意的方式。當我們在他們的平台上花費更多的時間,他們就會變得更成功,從而鼓勵了軟件質量的低劣競爭。我特別建議我的軟件開發同行退出這場競賽。真正的專業人士應該以他們精心打造的工作為傲,而不是表現得像寫代碼的猴子。

在 MacBook Pro 14,1 上安裝 Ubuntu 20.04 LTS

Ubuntu 20.04 剛剛問世,我迫不及待想要在我的 MacBook Pro 14.1 模型上試用並安裝它。在這篇文章中,我將詳述哪些東西能運作、哪些不能,以及如何解決這些問題。

安裝步驟很簡單:

  1. https://ubuntu.com/download/desktop 下載 Ubuntu 20.04 ISO 映像檔。
  2. 獲取一個 USB 隨身碟並透過 macOS 磁片工具將其格式化為 FAT。
  3. 使用 Etcher 建立可啟動的 USB 隨身碟。你可以在 這裡 下載該軟體。
  4. 在將 ISO 映像檔燒錄到 USB 隨身碟之後,重啟你的 Mac 並按 Option 鍵以選擇從 USB 碟機開機。

一旦你開始從 USB 隨身碟開機,你會注意到觸控板不起作用。然而,你可以使用外接滑鼠或繼續用鍵盤進行安裝。 (如下所述,稍後可以修復驅動程式問題。) 按照屏幕上的指示操作,你應該可以順利開啟 Ubuntu 操作系統。我對這個版本很欣賞的一點是,開機畫面是黑色的,而不是在以前的版本中看到的紫色。

以下特性開箱即用:

  • 有背光的鍵盤
  • 螢幕顯示和顯示卡
  • WiFi 連線
  • USB 插口
  • 電池

以下是預設不能運作的:

  • 揚聲器 (解決方法:使用外接耳機或透過外部監視器上的 HDMI,或者使用這個驅動程式修復)
  • 觸控板 (解決方法:使用外接滑鼠或安裝這裡的驅動程式)
  • 藍牙 (可以透過安裝這個驅動程式修復。請注意,如果在嘗試下載 5.4.0 版本時遇到 404 錯誤,修改腳本以使用 5.4.1 版本應該可以解決問題)
  • 攝像頭 (可以透過安裝這個驅動程式修復)

如果在安裝攝像頭驅動程式時遇到錯誤,你可以通過修改你的 Makefile 解決:

選擇:

    install:
      $(MAKE) -C $(KDIR) M=$(PWD) modules_install

更改為

    install:
      cp facetimehd.ko /lib/modules/$(shell uname -r)/extra; depmod -a

我推薦的安裝後的其他自定義操作包括:

  • 切換到深色模式。
  • 顯示電池百分比,運行:
  gsettings set org.gnome.desktop.interface show-battery-percentage true
  • 安裝 GNOME Tweaks。
  • 安裝 Ubuntu restricted extras:
  sudo apt install ubuntu-restricted-extras
  • 安裝 Atom 編輯器:
  wget -qO - [https://packagecloud.io/AtomEditor/atom/gpgkey](https://packagecloud.io/AtomEditor/atom/gpgkey) | sudo apt-key add -
  sudo sh -c 'echo "deb [arch=amd64] [https://packagecloud.io/AtomEditor/atom/any/](https://packagecloud.io/AtomEditor/atom/any/) any main" > /etc/apt/sources.list.d/atom.list'
  sudo apt-get update
  sudo apt-get install atom
  • 在鍵盤輸入時禁用觸控板:
  gsettings set org.gnome.desktop.peripherals.touchpad disable-while-typing true

有了這些步驟,你現在應該擁有一個安全且高效能的操作系統。雖然 Linux 的旅程可能充滿挑戰,但由於它提供的自定義選項和學習經驗,使得這個旅程變得非常有價值。不過要謹慎行事:雖然你可以創建各種自定義選項,但如果你不知道自己在做什麼,也可能會導致你的系統崩潰。如果你有任何問題或意見,歡迎隨時與我聯繫。

使用JavaScript處理瀏覽器關閉事件

在某些情況下,你可能不希望用戶關閉瀏覽器並退出會話。例如,如果用戶在填寫表單沒有保存,或者在還沒完成的付款交易中,他們嘗試關閉瀏覽器時,你可以提示用戶確認對話框。

以下是對話框在Chrome中的樣子:

在Firefox中:

這個功能可以通過在JavaScript中使用 beforeunload 事件來實現。將下面的代碼添加到你的網頁中:

window.addEventListener("beforeunload", event => {
  // 根據標準取消事件。
  event.preventDefault()
  // Chrome要求設置returnValue。
  event.returnValue = ""
})

請注意,只有在用戶與頁面有些許交互時,這個事件才會觸發。否則,這個功能將不會啟動。另外,用戶在以下三種情況下觸發事件:

  1. 用戶點擊關閉瀏覽器。
  2. 用戶點擊刷新頁面。
  3. 用戶點擊後退按鈕。

如果你想要移除這個確認對話框,例如在用戶已經保存表格或完成付款交易後,你可以這樣做:

window.removeEventListener("beforeunload", callback)

由於此對話框的主要目的是提醒用戶在離開之前保存他們的更改,所以沒有額外的事件監聽器來捕獲退出對話框的結果。換句話說,你無法確定用戶選擇了離開還是繼續留在頁面上。

要獲得更多信息,你可以查閱最新的MDN Web Docs: https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event

將 npm 模組導入 AWS Lambda 函數

當您在 Amazon Web Services (AWS) 上創建 Node.js Lambda 函數並開始使用線上編輯器進行編輯時,您可能會想要運行 npm install 並導入第三方庫,例如 lodash。不幸的是,透過網頁入口無法簡單地做到這一點。

要做到這一點,您需要在本地環境中編寫代碼,然後部署它。首先,在您的機器上創建一個資料夾,並將 index.js 文件複製到其中。接下來,運行以下命令以初始化您的項目並安裝相關性:

    npm init .
    npm install lodash --save

要在 index.js 中使用庫,添加以下行:

let _ = require("lodash")

當您完成編寫代碼後,使用以下命令壓縮整個資料夾,包括 node_modules 目錄:

    zip -r function.zip .

最後,使用 AWS CLI 工具從您的終端部署 zip 文件:

    aws lambda update-function-code --function-name yourFunctionName --zip-file fileb://function.zip

yourFunctionName 佔位符替換為您的函數名稱。如果部署成功,您應該會在終端中看到 "LastUpdateStatus": "Successful",然後您可以在 AWS 控制臺中進行函數測試。

修復WordPress插件安裝權限問題

問題

當我嘗試在WordPress中安裝插件時,遇到了以下錯誤:

安裝失敗:下載失敗。檔案串流的目標目錄不存在,或者無法寫入。

這個問題是由於內容文件夾的權限問題導致的。我已經以超級用戶(sudo su)的身份編輯了一些文件,但安裝需要ec2-user的寫入權限。

解決方案

假設你在AWS EC2實例上進行設定,並且已登入為ec2-user,並假設WordPress位於/var/www路徑中,執行以下命令以更改所有權:

sudo chown -R ec2-user:apache /var/www

改變所有權後,你現在應該可以成功地安裝插件。

修復WordPress,所有頁面都返回404未找到

問題

我遇到了一個關於WordPress的奇怪問題:首頁可以正常加載,但所有其他頁面都無法做到。相反,錯誤頁面顯示了這樣的信息:

未找到

找不到請求的URL在此服務器上。

然而,由於我已經將檔案從另一台服務器遷移過來,所以所有頁面都應該已經存在。我懷疑.htaccess檔案可能是問題所在,但經過幾個小時的故障排除,我仍然沒有線索。

解決方案

事實證明,在我的情況下,.htaccess檔案配置正確。問題在於其他地方。要解決它,编辑httpd.conf檔案:

    sudo vi /etc/httpd/conf/httpd.conf

找到以以下開頭的部分:

    <Directory "/var/www/html">

將配置從AllowOverride None改為:

    AllowOverride All

最後,重啟服務器:

    sudo systemctl restart httpd

做完這些,所有頁面都應該可以正常顯示。

使用AWS負載平衡器時,透過HTTPS設定修復WordPress的無盡重定向

問題

我在兩個位於不同可用性區域的Amazon Web Services (AWS) EC2實例上設置了一個WordPress博客。在這些實例前,配置了一個Elastic負載平衡器 (ELB),以將所有在80端口的HTTP請求重定向到443端口的HTTPS。由於wp-config.php文件未更新以反映此變更,請求仍在使用HTTP。為了糾正這個,我更新了以下值以使用HTTPS:

    define('WP_SITEURL', 'https://' . $_SERVER['HTTP_HOST'] . '/');
    define('WP_HOME', 'https://' . $_SERVER['HTTP_HOST'] . '/');

然而,這導致了一個無窮的重定向循環,最終導致一個錯誤,說明"重定向太多次"。

解決方案

要解決這個問題,需要在wp-config.php文件中添加以下行:

    $_SERVER['HTTPS'] = 'on';

這將修復此問題。這樣的配置可能難以排除故障,您可能會花費很多時間尋找一個簡單的解決方案。希望這篇文章能為您節省一些時間,如果您遇到這個特殊問題。

在Amazon Linux 2上安裝PHP 7.2而非PHP 5.4

問題

當你啟動一個新的 Amazon Linux 2 AMI 服務器並嘗試使用以下命令安裝 PHP:

yum install php

成功安裝後,如果你使用 php -v檢查版本,你會看到:

PHP 5.4.16 (cli) (建立日期: 2019年10月31號 18:34:05 )

不過,最新的PHP版本是7.2,你可能希望使用這個新版本。

解決方案

你可以透過 Amazon Linux Extras 啟動 PHP 7.2,使用以下命令:

sudo amazon-linux-extras enable php7.2

一旦已經啟動,按照接下來的指示完成安裝:

yum clean metadata
yum install php-cli php-pdo php-fpm php-json php-mysqlnd

就這樣。再次使用 php -v檢查 PHP 版本,現在應該會顯示:

PHP 7.2.28 (cli) (建立日期: 2020年3月2日 19:38:11 ) ( NTS )

使用Node.js讀取大型檔案

我最近面臨了分析由日誌文件組成的大數據集的任務。當我試圖在Excel中打開這個文件時,我的筆記本電腦簡直凍結了。鑑於可用工具的限制,我決定使用Node.js腳本解析該文件。

問題

要讀取一個小文件,你可能會使用以下腳本:

var fs = require("fs")

fs.readFile("path/mySmallFile.txt", "utf-8", (err, data) => {
  if (err) {
    throw err
  }
  console.log(data)
})

使用此腳本,你應該能夠讀取小文件的內容。然而,對於大文件,你可能會遇到緩存錯誤,例如 RangeError: 嘗試分配的緩衝區大於最大大小。該腳本將終止,產生類似於以下的錯誤:

Error: "toString" failed
  at stringSlice (buffer.js)
  at Buffer.toString (buffer.js)
  at FSReqWrap.readFileAfterClose [as oncomplete]

解決方案

要讀取一個大文件,你可以像這樣使用Node.js的本地 readline庫:

var fs = require("fs")
var readline = require("readline")

const rl = readline.createInterface({
  input: fs.createReadStream("path/largeFile.csv"),
  output: process.stdout,
  terminal: false,
})

rl.on("line", line => {
  console.log(line)
})

rl.on("pause", () => {
  console.log("Done!")
})

將文件路徑替換為你的大文件的路徑。在 on('line')函數內部,你可以逐行處理文件,例如將其解析為JSON並增加計數器。完成閱讀文件後,可以使用 on('pause')函數顯示最終總和。

使用這種方法,你現在應該能夠使用Node.js處理大量數據集。有關更多信息,請參閱官方文檔:Node.js 讀取API