2023年1月25日 星期三

ssh 連線出現 remote host identification has changed

原本的 Server IP 已經不是原來的 Server,所以之前初次連線儲存的 key 已不適用,連線時會出現「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 」錯誤。
>ssh 192.168.0.2
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:.............................................
Please contact your system administrator.
Add correct host key in C:\\Users\\xyz/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in C:\\Users\\xyz/.ssh/known_hosts:1
ECDSA host key for 192.168.0.2 has changed and you have requested strict checking.
Host key verification failed.

提示說明可以到使用者目錄底下的 .ssh/known_hosts 進行修改,比較方便的方式是使用 ssh-keygen 直接刪除該 Server IP 的 key 紀錄。
>ssh-keygen -R 192.168.0.2
# Host 192.168.0.2 found: line 1
C:\Users\xyz/.ssh/known_hosts updated.
Original contents retained as C:\Users\xyz/.ssh/known_hosts.old
刪除後,便可以如初次連線一樣,進行連線。




參考:

眼鏡鏡片袋度數標示的意思

眼鏡鏡片袋度數標示,依序大約是:
鏡片度數(SSPH) / 散光度數(CCYL) / 散光軸度(AXAXIS) / 老花度數(ADD)

其中:
  • 鏡片度數(SSPH):Spherical correction、球面度數,即一般講的鏡片度數。
    負的代表近視度數、正的代表遠視度數。
  • 散光度數(CCYL):Cylinder correction、柱狀度數,即一般講的散光度數。
  • 散光軸度(AXAXIS):散光除了度數還有軸度問題。所以配鏡使用庫存片時,眼鏡行人員有時會提醒,因為散光軸度,鏡片旋轉後,鏡片廠商的隱形記號可能超出鏡框而磨掉。數值:0~180度,0度等於180度。庫存片沒有標示軸度。
  • 老花度數(ADD):若是同時有近視、老花,且選擇使用遠近兩用的多焦點鏡片時。


若這樣的標示有兩組,是因為不同地區,習慣的標示方式不同,所以鏡片商用兩種方式標示,意思是一樣的。
那在台灣,習慣看哪一組?
可看散光度數(C、CYL)判斷:
  • 如果散光度數是用正值表示(例如:+1.00),表示用正散光方式標示
  • 如果散光度數是用負值表示(例如:-1.00),表示用負散光方式標示

台灣習慣看負散光的表示方式,所以看散光為負值的那一組,例如:
SPH:-8.00、CYL:-1.00、AXIS:10
表示近視度數800、散光度數100、散光軸度10


如果要換算成正散光的形式:
  • SPH 等於負散光的 SPH+CYL:-8.00+(-1.00)=-9.00
  • CYL 等於負散光的 CYL 數值,但改為正值:+1.00
  • AXIS 等於負散光的 CYL 加或減90度:10+90=100
得到正散光的表示方式
SPH:-9.00、CYL:+1.00、AXIS:100

正散光表示方式要變換成負散光表示方式,也是同樣的轉換方式,但 CYL 改成負值。
-9.00+(+1.00) = -8.00 (負散光 SPH )
+1.00 => -1.00 (負散光 CYL )
100-90=> 10 (負散光 AXIS )
如此,又轉換回原本的負散光表示方式。



其他:

PD:兩眼瞳距
SV:單光 (Single Vision)
AS:非球面 (Aspherical)
INDEX:鏡片折射率,例如 1.56、1.6、 1.67、1.74
OS(oculus sinister 拉丁語)、LE (left eye):左眼
OD(oculus dexter 拉丁語)、RE (right eye):右眼



參考:


2022年12月27日 星期二

PHP 7.3.x 升級到 PHP 8.1.x

 [PHP 7.3 -> PHP 8.1升級步驟]

環境:CentOS 7、已安裝 remi repository 的 PHP 7.3

步驟:(參考 remi repository 官網的說明)

  1. 安裝(更新) EPEL repository 設置
    # yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
  2. 安裝(更新) Remi repository 設置
    # yum install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
    我執行時發生錯誤
    Loaded plugins: fastestmirror
    Cannot open: https://rpms.remirepo.net/enterprise/remi-release-7.rpm. Skipping.
    Error: Nothing to do
    出現不能打開網址的錯誤,但在 windows 上用瀏覽器可以下載該網址檔案
    linux 上用 wget 測試
    # wget  https://rpms.remirepo.net/enterprise/remi-release-7.rpm
    --2022-07-25 01:02:03--  https://rpms.remirepo.net/enterprise/remi-release-7.rpm
    正在查找主機 rpms.remirepo.net (rpms.remirepo.net)... 109.238.14.107, 2a00:c70:1:109:238:14:107:1
    正在連接 rpms.remirepo.net (rpms.remirepo.net)|109.238.14.107|:443... 連上了。
    錯誤: cannot verify rpms.remirepo.net's certificate, issued by ‘/C=US/O=Let's Encrypt/CN=R3’:
      Issued certificate has expired.
    如果不想用安全模式連接 rpms.remirepo.net,請使用 ‘--no-check-certificate’ 選項
    cannot verify rpms.remirepo.net's certificate,應該是linux上的SSL憑證機構資料太舊,不認得發給rpms.remirepo.net憑證的機構
    更新(安裝) ca-certificates
    # yum install ca-certificates
    更新憑證機構資料後,便可以正常執行更新 Remi repository 設置的指令。

  3. 安裝(更新) yum-utils
    # yum install yum-utils
  4. 查看目前開啟(enabled)的 repository,PHP 是舊的 PHP7.3
    # yum repolist
    .....
    repo id             repo name                                                       status
    .....
    remi-php73          Remi's PHP 7.3 RPM repository for Enterprise Linux 7 - x86_64      446
    .....
  5. 查看所有 repository,可以發現多了PHP8.1(更新 Remi repository 設置後,即可看到新的 PHP 8.1)
    # yum repolist all
    .....
    remi-php73    Remi's PHP 7.3 RPM repository for Enterprise Linux 7 - x86_64    enabled:    446
    .....
    remi-php81    Remi's PHP 8.1 RPM repository for Enterprise Linux 7 - x86_64    disabled
    .....
  6. 關閉舊的 remi-php73,開啟 remi-php81
    # yum-config-manager --disable 'remi-php*'
    # yum-config-manager --enable   remi-php81

    查看目前開啟(enabled)的 repository,PHP 變成新的 PHP8.1
    # yum repolist
    ....
    remi-php81          Remi's PHP 8.1 RPM repository for Enterprise Linux 7 - x86_64      317
    .....
  7. 升級所有相關的php套件
    # yum update php\*

    重啟 PHP-FPM
    # systemctl restart php-fpm.service

    查看目前PHP版本
    # php -v
    Mon Jul 25 01:02:03 2022 (3137): Debug Loading blacklist file:  '/etc/php.d/opcache-default.blacklist'
    PHP 8.1.8 (cli) (built: Jul  5 2022 21:55:55) (NTS gcc x86_64)
    Copyright (c) The PHP Group
    Zend Engine v4.1.8, Copyright (c) Zend Technologies
        with Zend OPcache v8.1.8, Copyright (c), by Zend Technologies

    更新完,新裝的套件如下
    # yum list installed | grep php
    gd3php.x86_64                    2.3.3-7.el7.remi                    @remi
    oniguruma5php.x86_64             6.9.8-1.el7.remi                    @remi
    php.x86_64                       8.1.8-1.el7.remi                    @remi-php81
    php-bcmath.x86_64                8.1.8-1.el7.remi                    @remi-php81
    php-cli.x86_64                   8.1.8-1.el7.remi                    @remi-php81
    php-common.x86_64                8.1.8-1.el7.remi                    @remi-php81
    php-fpm.x86_64                   8.1.8-1.el7.remi                    @remi-php81
    php-gd.x86_64                    8.1.8-1.el7.remi                    @remi-php81
    php-mbstring.x86_64              8.1.8-1.el7.remi                    @remi-php81
    php-mysqlnd.x86_64               8.1.8-1.el7.remi                    @remi-php81
    php-opcache.x86_64               8.1.8-1.el7.remi                    @remi-php81
    php-pdo.x86_64                   8.1.8-1.el7.remi                    @remi-php81
    php-pecl-igbinary.x86_64         3.2.7-1.el7.remi.8.1                @remi-php81
    php-pecl-mcrypt.x86_64           1.0.5-1.el7.remi.8.1                @remi-php81
    php-pecl-memcached.x86_64        3.2.0-1.el7.remi.8.1                @remi-php81
    php-pecl-msgpack.x86_64          2.2.0~RC1-4.el7.remi.8.1            @remi-php81
    php-pecl-redis5.x86_64           5.3.7-1.el7.remi.8.1                @remi-php81
    php-soap.x86_64                  8.1.8-1.el7.remi                    @remi-php81
    php-sodium.x86_64                8.1.8-1.el7.remi                    @remi-php81
    php-xml.x86_64                   8.1.8-1.el7.remi                    @remi-php81

    原本舊的套件
    # yum list installed | grep php
    php.x86_64                       7.3.12-1.el7.remi                   @remi-php73
    php-bcmath.x86_64                7.3.12-1.el7.remi                   @remi-php73
    php-cli.x86_64                   7.3.12-1.el7.remi                   @remi-php73
    php-common.x86_64                7.3.12-1.el7.remi                   @remi-php73
    php-fpm.x86_64                   7.3.12-1.el7.remi                   @remi-php73
    php-gd.x86_64                    7.3.12-1.el7.remi                   @remi-php73
    php-json.x86_64                  7.3.12-1.el7.remi                   @remi-php73
    php-mbstring.x86_64              7.3.12-1.el7.remi                   @remi-php73
    php-mysqlnd.x86_64               7.3.12-1.el7.remi                   @remi-php73
    php-opcache.x86_64               7.3.12-1.el7.remi                   @remi-php73
    php-pdo.x86_64                   7.3.12-1.el7.remi                   @remi-php73
    php-pecl-igbinary.x86_64         3.0.1-2.el7.remi.7.3                @remi-php73
    php-pecl-mcrypt.x86_64           1.0.3-1.el7.remi.7.3                @remi-php73
    php-pecl-memcached.x86_64        3.1.4-1.el7.remi.7.3                @remi-php73
    php-pecl-msgpack.x86_64          2.0.3-1.el7.remi.7.3                @remi-php73
    php-pecl-redis4.x86_64           4.3.0-2.el7.remi.7.3                @remi-php73
    php-soap.x86_64                  7.3.12-1.el7.remi                   @remi-php73
    php-xml.x86_64                   7.3.12-1.el7.remi                   @remi-php73
  8. 原本有修改的設定擋會保留沿用,可查看一下跟新版設定檔的差異,通常是不需要修改
    # diff -y /etc/php.ini /etc/php.ini.rpmnew | less
    # diff -y /etc/php.d/10-opcache.ini /etc/php.d/10-opcache.ini.rpmnew | less
    .....



[程式不相容地方修改]
測試時,將 OPcache 關閉,似乎在新版會產生 Deprecated 的寫法,只有第一次產生 OPcache 快取時,才會出現 Deprecated 訊息。
(且由產生Deprecated的語法修改前後,可發現 OPcache 產生的快取檔大小一樣)
  1. 查看各版本間升級差異注意事項
  2. 不向後兼容的變更、廢棄(Deprecated)的功能,需要仔細查看。
    使用到不向後兼容的寫法,會直接出現錯誤,非改不可。
    使用到廢棄功能的寫法,雖然可執行,但會出現 Deprecated 訊息,提示哪個地方的寫法已經廢棄。
    雖然可以隱藏 Deprecated 訊息,但還是建議修改,因為之後某個版本,這些提示 Deprecated 的寫法就會被移除了,Deprecated 可以想成要正式移除前,給的緩衝時間提示。
  3. PHP 7.3 ~ PHP 8.1,不向後兼容的變更、廢棄的功能不少。
    有些難用關鍵字準確搜尋出來檢查。
    以下是我依我平時寫程式習慣、編輯器自動排版格式,將覺得可能採到雷的地方,用正規表達式(regex)搜尋全部程式碼文件,盡量減少須檢查的地方。
    • 槽狀嵌套的三元運算子(Nested ternary operator),須明確使用括號:
      1 ? 2 : 3 ? 4 : 5;   // 7.4.x deprecated、8.0.x 不向後兼容
      (1 ? 2 : 3) ? 4 : 5; // ok
      1 ? 2 : (3 ? 4 : 5); // ok
      我習慣三元運算子,盡量不用槽狀嵌套,若用到也會用括號,但還是不放心,
      所以用 regex 規則「 \? [\S ]+ \? 」 搜尋,找出一行內,出現兩次「 ? 」的地方檢查。
    • implode(string $separator, array $array) 參數中 $separator、$array 不可以互調。
      7.4.x deprecated、8.0.x 不向後兼容。

      看了這點,我才知道原來這兩個參數寫反,可以正常執行,
      印象中,應該沒寫反過,但以前不知道寫反可以正常執行,
      以為參數寫反會出錯,也許自己寫反了也沒發現,安全起見搜尋看看看。
      用 regex 規則「implode\([^'"]」 搜尋,找出「implode(」後面緊接著,不是「"」、也不是「、」的地方。
    • 函數(方法)有預設值的參數,後面若有必要參數,則默認值無效。
      function test($a = [], $b) {} // Before,8.0.x deprecated,8.1.x 不向後兼容(ArgumentCountError)
      function test($a, $b) {}      // After
      
      印象中以前將舊方法增加參數時,應該有導致此情況。 用 regex 規則「function [\S ]+\([\S ]+ = [\S ]+, \$[^=]+,[\S ]+\) \{」 搜尋,
      找出「function」後面,有出現「 = 」,但後面還有參數「 $」,卻沒有「 = 」的地方。
    • 不可以使用大刮號存取陣列。
      $array{"key"}; // 7.4.x deprecated、8.0.x 不向後兼容
      自己都是用中刮號存取陣列,但安全起見還是搜尋看看
      用 regex 規則「\$[\w]+\{」 搜尋,找出變數後面緊接著大刮號「{」的地方

    • 數字(numbers)跟數字字串(numeric strings)、非數字字串(non-numeric strings=>空字串、只有空白的字串也是非數字字串)的「==」比較修改。
      =>PHP8.0後改為
      https://www.php.net/manual/en/types.comparisons.php
      • 數字(numbers)跟數字字串(numeric strings)比較,跟之前一樣,按數字比較。
      • 數字(numbers)跟非數字字串(numeric strings)比較,PHP 8.0.x 後數字先轉成字串,再按字串比較。
      var_dump(0 == "0"); //PHP7;true,PHP8:true(同 "0" == "0")
      var_dump("0" == "0"); //PHP7、PHP8 均為 true
      
      var_dump(0 == "0.0"); //PHP7;true,PHP8:true(同 "0" == "0.0")
      var_dump("0" == "0.0"); //PHP7、PHP8 均為 true
      
      var_dump(0 == "foo"); //PHP7;true,PHP8:false(同 "0" == "foo")
      var_dump("0" == "foo"); //PHP7、PHP8 均為 false
      
      var_dump(0 == ""); //PHP7;true,PHP8:false(同 "0" == "")
      var_dump("0" == ""); //PHP7、PHP8 均為 false
      
      
      var_dump(42 == " 42"); //PHP7;true,PHP8:true(同 "42" == " 42")
      var_dump("42" == " 42"); //PHP7、PHP8 均為 true
      
      var_dump(42 == "42foo"); //PHP7;true,PHP8:false(同 "42" == "42foo")
      var_dump("42" == "42foo"); //PHP7、PHP8 均為 false
      
      var_dump(0 < "0"); //PHP7;false,PHP8:false(同 "0" < "0")
      var_dump("0" < "0"); //PHP7、PHP8 均為 false
      
      var_dump(0 < "0.0"); //PHP7;false,PHP8:false(同 "0" < "0.0")
      var_dump("0" < "0.0"); //PHP7、PHP8 均為 false
      
      var_dump(0 < "foo"); //PHP7;false,PHP8:true(同 "0" < "foo")
      var_dump("0" < "foo"); //PHP7、PHP8 均為 true
      
      var_dump(0 > ""); //PHP7;false,PHP8:true(同 "0" > "")
      var_dump("0" > ""); //PHP7、PHP8 均為 true
      
      var_dump(42 < " 42"); //PHP7;false,PHP8:false(同 "42" < " 42")
      var_dump("42" < " 42"); //PHP7、PHP8 均為 false
      
      var_dump(42 < "42foo"); //PHP7;false,PHP8:true(同 "42" < "42foo")
      var_dump("42" < "42foo"); //PHP7、PHP8 均為 true
      

      這點算是大魔王,就看平時寫程式習慣了。
      還有沒提到的,兩邊都是字串的比較,PHP8 和PHP7 有些也有差異:
      var_dump("  42  " == "42"); //PHP7.3、PHP7.4:false,PHP8.0、PHP8.1:true
      var_dump("  42" == "42"); //PHP7、PHP8 均為 true
      var_dump("42  " == "42"); //PHP7.3、PHP7.4:false,PHP8.0、PHP8.1:true
      var_dump(" 42  " == "   42     "); //PHP7.3、PHP7.4:false,PHP8.0、PHP8.1:true
      var_dump(" " == "  "); //PHP7、PHP8 均為 false
    • PHP 8.1 有兩個 Deprecated 的項目,雖然可執行,但會出現 Deprecated,也找出來修改,避免之後版本移除,變成不相容
      • Passing null to non-nullable parameters of built-in functions
        =>將 null 傳給內建函式中,不能為 null 的參數
        =>例如,preg_match(string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0)
        preg_match("/abc/", null),之前會默默執行,PHP8.1 會出現 Deprecated 訊息
        =>PHP 7.4新增的Null coalescing assignment operator,在此處很有用
        preg_match("/abc/", $aa ?? "");//當 $aa 是 null 時,將 $aa 改成是空字串
      • Implicit incompatible float to int conversions
        =>帶小數的浮點數,隱含轉換為整數
        =>例如,srand(int $seed = 0, int $mode = MT_RAND_MT19937)
        srand(10.123),之前會默默轉成整數執行,PHP8.1 會出現 Deprecated 訊息
        Implicit conversion from float to int loses precision
    • 嘗試以array方式訪問null、bool、int、float、resource
      例如 $null["key"],將拋出錯誤訊息,不向後兼容,7.4拋出notice、8.0拋出Warning 
      =>在PHP7.3,這些資料型態用陣列方式存取,結果會是null,沒有錯誤訊息。
      PHP7.4、8.0後,用陣列方式存取,結果雖然也是null,但多了notice、Warning訊息,
      所以若變數某些情況可能不會是array,例如可能是false,也要特別留意,才不會出現notice、Warning訊息。
      =>這點無法用關鍵字、正規式搜尋找出來,因通常出現在函式(方法)回應值,成功回傳array、失敗回傳false(null)..的情況
    • MySQL Driver(PHP8.1不向後相容)
      Integers and floats in result sets will now be returned using native PHP types instead of strings when using emulated prepared statements. This matches the behavior of native prepared statements.The previous behaviour can be restored by enabling the PDO::ATTR_STRINGIFY_FETCHES option.
      之前的版本(php-mysqlnd,PHP5.4後預設使用mysqlnd),若 PDO 設定 PDO::ATTR_EMULATE_PREPARES=>true(預設值),將使用 PHP 模擬的 prepare statement,而不是在資料庫做 prepare statement,但 PHP 模擬的行為,一直有一個問題:取資料庫中的 int、float 資料時,會變成字串形式返回。
      PHP 8.1 之後,不管有沒有啟用 PDO::ATTR_EMULATE_PREPARES,都將忠實的返回 int、float,不會再返回成字串。

      如果想維持返回的資料為字串,可以另外設定 PDO::ATTR_STRINGIFY_FETCHES => true
      以我的習慣,可能有影響的地方,大概是這類型的資料:
      "0.12" === $aa;
      "0" === $aa;
      "1" === $aa;
      
      $aa === "0.12";
      $aa === "0";
      $aa === "1";
      
      "0.12" !== $aa;
      "0" !== $aa;
      "1" !== $aa;
      
      $aa !== "0.12";
      $aa !== "0";
      $aa !== "1";
      分別寫4個正規式,搜尋找出檢查
      • [\"\']{1}[\d\.]+[\"\']{1} ===
      • === [\"\']{1}[\d\.]+[\"\']{1}』
      • [\"\']{1}[\d\.]+[\"\']{1} !==
      • !== [\"\']{1}[\d\.]+[\"\']{1}

      PDO::ATTR_EMULATE_PREPARES 說明
          Note: Only available for the OCI, Firebird, and MySQL drivers.
          Whether enable or disable emulation of prepared statements.
          Some drivers do not support prepared statements natively or have limited support for them.
          If set to true PDO will always emulate prepared statements, otherwise PDO will attempt to use native prepared statements.
          In case the driver cannot successfully prepare the current query, PDO will always fall back to emulating the prepared statement.

      PDO::ATTR_STRINGIFY_FETCHES 說明
          Whether to convert numeric values to strings when fetching. Takes a value of type bool: true to enable and false to disable.




參考:


2022年10月26日 星期三

減少 MacBook Air M1睡眠時的 SSD 硬碟寫入量

[環境]
MacBook Air (M1, 2020)、macOS 12.6、接外接電源

[情況]
某天發現 MacBook 睡眠的時間越久,SSD 硬碟的寫入量,會越來越多,
甚至有次突然就多了幾十G寫入量。

依照在 windows 的經驗,應該是睡眠時,設定成將記憶體資料寫入硬碟,
至於睡眠越久硬碟寫入量越多,可能是某些因素系統被喚醒再繼續睡眠。

簡單測試了一下,蓋上 MacBook 前,特意將軟體都關閉,使用的記憶體大幅降低後,
隔天再觀察,SSD 增加的寫入量,明顯少了。
可見睡眠將記憶體資料寫入硬碟,應該是主要因素之一。

查睡眠喚醒次數,可發現自動喚醒的次數(Dark Wake)遠超過手動喚醒(User Wake)。
% pmset -g stats
Sleep Count:1334
Dark Wake Count:1313
User Wake Count:24


[目的]
考量自己的使用習慣,我不在意睡眠睡到沒電,無法保留原本在記憶體中的狀態,因為睡眠前我都會儲存進行中的作業。
所以預計將設定改成:
  1. 睡眠時,不將記憶體資料寫入硬碟。
  2. 睡眠時,不自動喚醒。(此項最後只有大幅減少自動喚醒次數,變成 2 小時喚醒一次)

 
[處理方式]
找了相關資料,經過一段時間的觀察測試,發現自動喚醒(Dark Wake)似乎無法100%禁止。
尤其我測試的某些結果,反跟網上所述恰恰相反,不確定是否作業系統版本不同的影響。
所以最終只設定成在我目前的環境下,自動喚醒(Dark Wake)次數盡量最少。

先查看預設的電源參數設定
% pmset -g custom
Battery Power:
 Sleep On Power Button 1
 lowpowermode         0
 standby              1
 ttyskeepawake        1
 hibernatemode        3
 powernap             1
 hibernatefile        /var/vm/sleepimage
 displaysleep         2
 sleep                1
 tcpkeepalive         1
 lessbright           1
 disksleep            10
AC Power:
 Sleep On Power Button 1
 lowpowermode         0
 standby              1
 ttyskeepawake        1
 hibernatemode        3
 powernap             1
 hibernatefile        /var/vm/sleepimage
 displaysleep         10
 womp                 1
 networkoversleep     0
 sleep                1
 tcpkeepalive         1
 disksleep            10

  1. 睡眠時,不將記憶體資料寫入硬碟
    系統睡覺有兩種狀態:
    Sleep(睡眠):保持對記憶體供電,將記憶體資料保存著,斷電資料會不見。
    Hibernate(休眠):將記憶體資料寫入硬碟,斷電還會存在。

    電源參數設定值:
    hibernatemode=0,只將資料保存在記憶體。(持續對記憶體供電)
    hibernatemode=3,除了將資料保存在記憶體,也寫入硬碟。(持續對記憶體供電)
    hibernatemode=25,將記憶體資料寫入硬碟保存後,就不保留在記憶體。(不對記憶體供電)

    是否將記憶體資料寫入硬碟,也受 standby、autopoweroff 影響:
    使用電池時,在條件符合的情況下,會觸發 standby,也會進入 Hibernate,將記憶體資料寫入硬碟。
    插電源時,在條件符合的情況下,會觸發 autopoweroff,也會進入 Hibernate,將記憶體資料寫入硬碟。

    但 standby、autopoweroff 這兩個相關的設定值,要有支援才會有。
    由 pmset -g cap 可查看目前供電條件下,可設定的參數

    使用電池時,可設定的參數:
    % pmset -g cap 
    Capabilities for Battery Power:
     displaysleep
     disksleep
     sleep
     lessbright
     standby
     powernap
     ttyskeepawake
     hibernatemode
     hibernatefile
     tcpkeepalive
     lowpowermode

    插電源時,可設定的參數:
    % pmset -g cap
    Capabilities for AC Power:
     displaysleep
     disksleep
     sleep
     womp
     standby
     powernap
     ttyskeepawake
     hibernatemode
     hibernatefile
     tcpkeepalive
     lowpowermode

    可發現我的環境只有 hibernatemode、standby,沒有 autopoweroff

    我不想將記憶體資料寫入硬碟,所以將 hibernatemode、standby、autopoweroff 都設為 0
    (因為我沒有 autopoweroff 的設定,所以沒執行 sudo pmset -a autopoweroff 0 也沒差)
    % sudo pmset -a hibernatemode 0
    % sudo pmset -a standby 0
    % sudo pmset -a autopoweroff 0
    pmset 參數說明:
    -b:電池,battery
    -c:插電源,charger (wall power)
    -u:UPS
    -a:全部

  2. 睡眠時,不自動喚醒
    關閉網路喚醒:
    這可以到「系統偏好設定」->「電池」->「電源轉接器」->取消勾選「進行網路連線時喚醒電腦」
    或下指令設定
    % sudo pmset -a womp 0

    關閉 powernap 高效小睡,預設開啟 powernap 時,會讓系統趁睡眠時,醒過來做一些事:
    % sudo pmset -a powernap 0
    (官網說明,當 Mac 進入睡眠並使用電池電力時,「高效小睡」會:檢查「郵件」中的新郵件、更新「行事曆」事件、更新其他 iCloud 事件、當 Mac 插上電源轉接器時,「高效小睡」還可以進行下載軟體更新項目和執行「時光機」備份等作業。)

    到此設定,發生 DarkWake 的情況,只剩這些:
    % pmset -g log | egrep "\b(Sleep|Wake|DarkWake|Start)\s{2,}"
    .....
    2022-10-13 04:09:14 +0800 Sleep               	Entering Sleep state due to 'Clamshell Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-13 06:09:14 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 45 secs   
    2022-10-13 06:09:59 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-13 08:09:59 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 42 secs   
    2022-10-13 08:10:41 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7199 secs 
    2022-10-13 10:10:40 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 46 secs   
    2022-10-13 10:11:26 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-13 12:11:26 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 48 secs   
    2022-10-13 12:12:14 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-13 14:12:14 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 46 secs   
    2022-10-13 14:13:00 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-13 16:13:00 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 42 secs   
    2022-10-13 16:13:42 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-13 18:13:42 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 46 secs   
    2022-10-13 18:14:28 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-13 20:14:28 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 45 secs   
    2022-10-13 20:15:13 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-13 22:15:13 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 46 secs   
    2022-10-13 22:15:59 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-14 00:15:59 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 46 secs   
    2022-10-14 00:16:45 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-14 02:16:45 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 45 secs   
    2022-10-14 02:17:30 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-14 04:17:30 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 44 secs   
    2022-10-14 04:18:14 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-14 06:18:14 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 44 secs   
    2022-10-14 06:18:58 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 7200 secs 
    2022-10-14 08:18:58 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:80%) 46 secs   
    2022-10-14 08:19:44 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:80%) 4162 secs 
    2022-10-14 09:29:06 +0800 Wake                	Wake from Deep Idle [CDNVA] : due to SMC.OutboxNotEmpty smc.70070000 lid/UserActivity Assertion Using AC (Charge:80%)


    原本要再如網上說的,設定睡眠時,關閉持續網路連線,但結果 DarkWake 反而暴增,所以最終此項不設定:
    % sudo pmset -a tcpkeepalive 0
    Warning: This option disables TCP Keep Alive mechanism when sytem is sleeping. 
    This will result in some critical features like 'Find My Mac' not to function properly.
    (關閉時,會出現警告,説將無法使用 Find My Mac)

    蓋上筆電,睡眠前
    % pmset -g stats              
    Sleep Count:628
    Dark Wake Count:616
    User Wake Count:13

    一天多後,打開筆電,自動喚醒 DarkWake 暴增兩千多次
    % pmset -g stats
    Sleep Count:3494
    Dark Wake Count:3482
    User Wake Count:14

    查看紀錄
    % pmset -g log | egrep "\b(Sleep|Wake|DarkWake|Start)\s{2,}"
    .....
    2022-10-14 09:51:06 +0800 Sleep               	Entering Sleep state due to 'Clamshell Sleep':TCPKeepAlive=disabled Using AC (Charge:80%) 1718 secs 
    2022-10-14 10:19:44 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:80%) 45 secs   
    2022-10-14 10:20:29 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=disabled Using AC (Charge:80%) 1 secs    
    2022-10-14 10:20:30 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:80%) 45 secs   
    2022-10-14 10:21:15 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=disabled Using AC (Charge:80%) 0 secs    
    2022-10-14 10:21:15 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:80%) 44 secs   
    2022-10-14 10:21:59 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=disabled Using AC (Charge:80%) 1 secs    
    2022-10-14 10:22:00 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:80%) 45 secs   
    2022-10-14 10:22:45 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=disabled Using AC (Charge:80%) 0 secs    
    2022-10-14 10:22:45 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:80%) 44 secs   
    2022-10-14 10:23:29 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=disabled Using AC (Charge:80%) 1 secs    
    2022-10-14 10:23:30 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:80%) 45 secs   
    2022-10-14 10:24:15 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=disabled Using AC (Charge:80%) 0 secs    
    2022-10-14 10:24:15 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:80%) 45 secs   
    2022-10-14 10:25:00 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=disabled Using AC (Charge:80%) 1 secs    
    2022-10-14 10:25:01 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:80%) 45 secs   
    2022-10-14 10:25:46 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=disabled Using AC (Charge:80%) 0 secs    
    2022-10-14 10:25:46 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:80%) 45 secs 
    .....
    2022-10-15 22:33:01 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=disabled Using AC (Charge:79%) 0 secs    
    2022-10-15 22:33:01 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:79%) 45 secs   
    2022-10-15 22:33:46 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=disabled Using AC (Charge:79%) 1 secs    
    2022-10-15 22:33:47 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/ Using AC (Charge:79%) 20 secs   
    2022-10-15 22:34:07 +0800 Wake                	DarkWake to FullWake from Deep Idle [CDNVA] : due to HID Activity Using AC (Charge:79%)
    可發現,剛開始蓋上蓋子,有進入 sleep,但第一次 DarkWake 後,便無法進入sleep (sleep 後會馬上 DarkWake),導致 DarkWake 次數大增。

    也因為一 sleep 後馬上 DarkWake,所以幾乎都處於 DarkWake 的狀態,因此打開筆電,很容易遇到系統剛好處於 DarkWake,也有幸因此見到不同訊息的 Wake 訊息:
    之前在Sleep狀態打開筆電,是
    Wake                	Wake from Deep Idle [CDNVA] : due to SMC.OutboxNotEmpty smc.70070000 lid/UserActivity Assertion Using AC (Charge:80%)
    這次在DarkWake狀態打開筆電,是
    Wake                	DarkWake to FullWake from Deep Idle [CDNVA] : due to HID Activity Using AC (Charge:79%)


    因為 tcpkeepalive 設為 0 後,情況更嚴重,所以將 tcpkeepalive 改回 1
    % sudo pmset -a tcpkeepalive 1
    再蓋上筆電一天多,觀察紀錄,變回固定 sleep 兩小時(7200秒),才會因 rtc/Maintenance 醒過來(DarkWake)
    % pmset -g log | egrep "\b(Sleep|Wake|DarkWake|Start)\s{2,}"
    .....
    2022-10-16 03:50:42 +0800 Sleep               	Entering Sleep state due to 'Clamshell Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-16 05:50:42 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 43 secs   
    2022-10-16 05:51:25 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-16 07:51:25 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 46 secs   
    2022-10-16 07:52:11 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-16 09:52:11 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 45 secs   
    2022-10-16 09:52:56 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 2725 secs 
    2022-10-16 10:38:21 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to SMC.OutboxNotEmpty smc.70070000 wifibt wlan/ Using AC (Charge:79%) 45 secs   
    2022-10-16 10:39:06 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-16 12:39:06 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 45 secs   
    2022-10-16 12:39:51 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-16 14:39:51 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 45 secs   
    2022-10-16 14:40:36 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 207 secs  
    2022-10-16 14:44:03 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to SMC.OutboxNotEmpty smc.70070000 wifibt wlan/ Using AC (Charge:79%) 45 secs   
    2022-10-16 14:44:48 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-16 16:44:48 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 44 secs   
    2022-10-16 16:45:32 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-16 18:45:32 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 45 secs   
    2022-10-16 18:46:17 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-16 20:46:17 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 46 secs   
    2022-10-16 20:47:03 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-16 22:47:03 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 45 secs   
    2022-10-16 22:47:48 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-17 00:47:48 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 45 secs   
    2022-10-17 00:48:33 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-17 02:48:33 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 44 secs   
    2022-10-17 02:49:17 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 7200 secs 
    2022-10-17 04:49:17 +0800 DarkWake            	DarkWake from Deep Idle [CDN] : due to NUB.SPMI0Sw3IRQ nub-spmi.0x02 rtc/Maintenance Using AC (Charge:79%) 46 secs   
    2022-10-17 04:50:03 +0800 Sleep               	Entering Sleep state due to 'Maintenance Sleep':TCPKeepAlive=active Using AC (Charge:79%) 2345 secs 
    2022-10-17 05:29:08 +0800 Wake                	Wake from Deep Idle [CDNVA] : due to SMC.OutboxNotEmpty smc.70070000 lid/UserActivity Assertion Using AC (Charge:79%)
    所以目前大概就是維持目前的設定,至少需兩小時才會DarkWake一次,而且硬碟寫入量也超少。

    最終的電源參數設定值:
    (注意:如果到系統偏好設定裡的電源設定,進行回復預設值操作,即使介面上沒有的設定,也會回復預設值)
    % pmset -g custom                                           
    Battery Power:
     Sleep On Power Button 1
     lowpowermode         0
     standby              0
     ttyskeepawake        1
     hibernatemode        0
     powernap             0
     hibernatefile        /var/vm/sleepimage
     displaysleep         2
     sleep                1
     tcpkeepalive         1
     lessbright           1
     disksleep            10
     SleepServices        0
    AC Power:
     Sleep On Power Button 1
     lowpowermode         0
     standby              0
     ttyskeepawake        1
     hibernatemode        0
     powernap             0
     hibernatefile        /var/vm/sleepimage
     displaysleep         10
     womp                 0
     networkoversleep     0
     sleep                1
     tcpkeepalive         1
     disksleep            10
     SleepServices        0



參考:



2022年9月27日 星期二

CentOS 安裝 NFS Server

[環境]

三台 CentOS 7:
NFS Server (192.168.0.10)
Client (192.168.0.2)
Client (192.168.0.3)


[目的]

NFS Server (192.168.0.10) 建立兩個資料夾(/home/nfsA、/home/nfsB),
開放給兩個 Client(192.168.0.2、192.168.0.3) 存取。


[步驟]

  • NFS Server
    1. 安裝 NFS
      $ yum install nfs-utils
    2. 建立要分享的資料夾
      $ mkdir /home/nfsA
      $ mkdir /home/nfsB
    3. 編輯設定檔,加入兩個要分享的資料夾,並設定兩個 Client(192.168.0.2、192.168.0.3) 有存取權限。
      $ vi /etc/exports
      設定檔內容
      /home/nfsA 192.168.0.2(rw,sync,no_root_squash,no_all_squash,no_subtree_check) 192.168.0.3(rw,sync,no_root_squash,no_all_squash,no_subtree_check)
      /home/nfsB 192.168.0.2(rw,sync,no_root_squash,no_all_squash,no_subtree_check) 192.168.0.3(rw,sync,no_root_squash,no_all_squash,no_subtree_check)
      注意:
      設定值 rw,sync,no_root_squash,no_all_squash,no_subtree_check,
      請依個人環境需求設定,可用的設定值、效果,可用 man exports 查看。
      $ man exports
      .....
      rw     Allow both read and write requests on this NFS volume.
             The default is to disallow any request which changes the filesystem.
             This can also be made explicit by using the ro option.
      .....
      sync   Reply to requests only after the changes have been committed to stable storage (see async above).
             In  releases  of nfs-utils up to and including 1.0.0, the async option was the default.
             In all releases after 1.0.0, sync is the default, and async must be explicitly requested if needed.
             To help make system administrators aware of this change, exportfs will issue a warning if neither sync nor async is specified.
      .....
      no_subtree_check
             This option disables subtree checking, which has mild security implications, but can improve reliability in some circumstances.
      
             If a subdirectory of a filesystem is exported, but the whole filesystem isn't then whenever a NFS request arrives,
             the server must check not only that  the  accessed  file  is  in  the  appropriate filesystem (which is easy) but also that it is in the exported tree (which is harder).
             This check is called the subtree_check.
      
             In  order  to  perform  this  check, the server must include some information about the location of the file in the "filehandle" that is given to the client.
             This can cause problems with accessing files that are renamed while a client has them open (though in many simple cases it will still work).
      
             subtree checking is also used to make sure that files inside directories to which only root has access can only be accessed if the filesystem is exported with no_root_squash (see  below),  even  if
             the file itself allows more general access.
      
             As  a  general guide, a home directory filesystem, which is normally exported at the root and may see lots of file renames,
             should be exported with subtree checking disabled.  A filesystem which is mostly readonly,
             and at least doesn't see many file renames (e.g. /usr or /var) and for which subdirectories may be exported, should probably be exported with subtree checks enabled.
      
             The default of having subtree checks enabled, can be explicitly requested with subtree_check.
      
             From release 1.1.0 of nfs-utils onwards, the default will be no_subtree_check as subtree_checking tends to cause more problems than it is worth.
             If you  genuinely  require  subtree  checking,  you should explicitly put that option in the exports file.
             If you put neither option, exportfs will warn you that the change is pending.
      .....
      root_squash
             Map requests from uid/gid 0 to the anonymous uid/gid.
             Note that this does not apply to any other uids or gids that might be equally sensitive,
             such as user bin or group staff.
             (client 端使用 root 操作掛載的目錄時,NFS Server 會將 client 端的 root 對應成 NFS Server 上的匿名帳號)
      no_root_squash
             Turn off root squashing. This option is mainly useful for diskless clients.
      
      all_squash
             Map all uids and gids to the anonymous user.
             Useful for NFS-exported public FTP directories, news spool directories, etc.
             The opposite option is no_all_squash, which is the default setting.
    4. 啟動服務
      $ systemctl enable rpcbind
      $ systemctl enable nfs-server
      $ systemctl enable nfs-lock
      $ systemctl enable nfs-idmap
      $ systemctl start rpcbind
      $ systemctl start nfs-server
      $ systemctl start nfs-lock
      $ systemctl start nfs-idmap
    5. 開放防火牆
      $ firewall-cmd --permanent --zone=public --add-service=nfs
      $ firewall-cmd --permanent --zone=public --add-service=mountd
      $ firewall-cmd --permanent --zone=public --add-service=rpc-bind
      $ firewall-cmd --reload
      $ firewall-cmd --list-all --zone=public
  • Client
    1. 安裝 nfs-utils、libnfsidmap,啟動 rpcbind
      $ yum install nfs-utils libnfsidmap
      $ systemctl enable rpcbind
      $ systemctl start rpcbind
    2. 掛載 NFS Server 資料夾
      • 方法1:手動掛載
        $ mkdir /mnt/nfsA
        $ mkdir /mnt/nfsB
        $ showmount -e 192.168.0.10
        $ mount -t nfs 192.168.0.10:/home/nfsA /mnt/nfsA
        $ mount -t nfs 192.168.0.10:/home/nfsB /mnt/nfsB
      • 方法2:使用 autofs 自動掛載
        [安裝 autofs]
        $ yum install autofs
        $ systemctl enable autofs.service

        [建立新檔案 /etc/auto.mymnt-nfsA,裡面寫掛載 192.168.0.10:/home/nfsA/ 的語法]
        $ vi /etc/auto.mymnt-nfsA
        檔案內容
        * -rw,bg,soft,rsize=32768,wsize=32768 192.168.0.10:/home/nfsA/&

        [建立新檔案 /etc/auto.mymnt-nfsB,裡面寫掛載 192.168.0.10:/home/nfsB/ 的語法]
        $ vi /etc/auto.mymnt-nfsB
        檔案內容
        * -rw,bg,soft,rsize=32768,wsize=32768 192.168.0.10:/home/nfsB/&


        [建立新檔案 /etc/auto.master.d/mymnt.autofs,裡面寫上面兩個掛載語法,要掛載到哪個路徑]
        $ vi /etc/auto.master.d/mymnt.autofs
        檔案內容
        /mnt/nfsA /etc/auto.mymnt-nfsA
        /mnt/nfsB /etc/auto.mymnt-nfsB


        [重啟 autofs]
        $ systemctl restart autofs

        [掛載語法說明(以 /etc/auto.mymnt-nfsA 內容為例)]
        * -rw,bg,soft,rsize=32768,wsize=32768 192.168.0.10:/home/nfsA/&
        最前面的「*」,表示 client 端 /mnt/nfsA 下的所有目錄
        最後面的「&」,表示 NFS Server 的 192.168.0.10:/home/nfsA 底下所有目錄
        「&」對應到「*」
        例如:192.168.0.10:/home/nfsA/abc 會掛載成 client 端的 /mnt/nfsA/abc




參考: