2022年6月16日 星期四

Disk protocol

 


** Disk protocol

ATA 指令集 與 SCSI 指令集

操作系統主要有一種標準協議:ATA指令集 與 SCSI指令集。

與磁盤通信層,同樣遵循ISO分層標準模式:傳輸物理層、鏈路層和應用層、指令應用層。

物理上,ATA和SCSI本來都是整協議接口標準,不止是指令,還制定了物理層、連接層、傳輸層的規範,同時包括接口。

ATA 進化 接口標準,同時應用又支持 SCSI 指令集, 那這塊磁盤就是 ATAPI 設備。

後來,SCSI 也加入了特性支持,在 SCSI 鏈路上運行 ATA 指令。


序列式SCSI(英語:Serial Attached SCSI,簡稱SAS)是一種電腦集線的技術,其功能主要是作為週邊零件的數據傳輸,

例如:硬碟、CD-ROM等裝置而設計的介面。

序列式SCSI 由並列SCSI物理儲存介面演化而來,是由ANSI INCITS T10技術委員會(T10 committee(頁面存檔備份,存於網際網路檔案館))開發及維護的新的儲存介面標準。

與並列方式相比,序列方式能提供更快速的通信傳輸速度以及更簡易的組態。此外SAS並支援與序列式ATA(SATA)裝置相容,且兩者可以使用相類似的電纜。

SAS是點對點(point-to-point)連接,並允許多個埠集中於單個控制器上,其可以內建於主機板(mother board)當中;也可另外添加。該技術建立在強大的並列SCSI通信技術基礎上。

SAS是採用SATA相容的電纜線採取點對點連接方式,從而在計算機系統中不需要建立雛菊鏈結(daisy-chaining)方式便可簡單地實現線纜安裝。



1、AHCI模式

AHCI 是英特爾制定的主機接口標準。AHCI是為SATA 設計的控制器接口, AHCI 標准設計了一個AHCI來控制系統內存與 SATA 之間的數據交換。

AHCI(Serial ATA Advanced Host Controller Interface,並列ATA進階主機控制介面/),是在Intel的指導下,由多家公司聯合研發的介面標準,

它允許存儲驅動程式啟用進階串列 ATA 功能,如本機命令佇列和熱插跋,其研發小組成員主要包括Intel、AMD、戴爾、Marvell、邁拓、微軟、Red Hat、希捷和StorageGear等著名企業。

優點: 1. ACHI支援NCQ技術; 2.讀寫速度更快; 3.支援熱插跋。


2、AHCI 與 IDE 模式的區別

IDE(Integrated Device Electronics),整合驅動電子裝置,一般會作為ATA硬體的埠,它的本意是指把“硬碟控制器”與“盤體”整合在一起的硬碟驅動器。 

IDE模式可以將SATA盤映射類比成普通IDE硬碟,無需額外載入SATA驅動。但不支援任何SATA介面的新特性。



** 硬碟接口

    IDE 、SATA 、mSATA 、M.2 、AHCI、NVMe

    硬碟接口通俗理解就是硬碟和計算機其他部分相互連接的方式,各種接口擁有自己獨特的用途和適用的範圍!

    硬碟接口是硬碟與主機系統間的連接部件,作用是在硬碟緩存和主機內存之間傳輸數據。

    不同的硬碟接口決定著硬碟與計算機之間的連接速度,在整個系統中,硬碟接口的優劣直接影響著程序運行快慢和系統性能好壞。

    IDE -> ATA -> PATA -> SATA

    SCSI -> SAS


1. IDE接口

其英文名稱:Integrated Drive Electronics,常見的2.5英寸IDE硬碟接口它的本意是指把「硬碟控制器」與「盤體」集成在一起的硬碟驅動器。

IDE代表著硬碟的一種類型,但在實際的應用中,人們也習慣用IDE來稱呼最早出現IDE類型硬碟ATA-1,這種類型的接口隨著接口技術的發展已經被淘汰了,

而其後發展分支出更多類型的硬碟接口,比如ATA、Ultra ATA、DMA、Ultra DMA等接口都屬於IDE硬碟。其特點為:價格低廉,兼容性強,性價比高,數據傳輸慢,不支持熱插拔等等。

而現在,硬碟接口幾乎SATA是標配置,市場上幾乎沒有IDE接口的硬碟了。

 

優點:該接口的硬碟價格低廉、兼容性強、性價比高。

缺點:數據傳輸速度慢、線纜長度過短、連接設備少、不支持熱插拔、、接口速度的可升級性差。


2. SCSI接口類型

其英文名稱為:Small Computer System Interface。SCSI並不是專門為硬碟設計的接口,是一種廣泛應用於小型機上的高速數據傳輸技術。

SCSI接口具有應用範圍廣、多任務、帶寬大、CPU占用率低,以及熱插拔等優點,但較高的價格使得它很難如IDE硬碟般普及,因此SCSI硬碟主要應用於中、高端伺服器和高檔工作站中。

其特點為:傳輸速率高、讀寫性能好、可連接多個設備、可支持熱插拔,但是價格相對來說比較貴。


3. SATA接口

其英文名稱為:Serial Advanced Technology Attachment。使用SATA(Serial ATA)口的硬碟又叫串口硬碟,是未來PC機硬碟的趨勢。

Serial ATA採用串行連接方式,串行ATA總線使用嵌入式時鐘信號,具備了更強的糾錯能力,與以往相比其最大的區別在於能對傳輸指令(不僅僅是數據)進行檢查,

如果發現錯誤會自動矯正,這在很大程度上提高了數據傳輸的可靠性。串行接口還具有結構簡單、支持熱插拔的優點。

  

4. SAS接口類型

其英文名稱為:Serial Attached SCSI。其可以向下兼容SATA。具體來說,二者的兼容性主要體現在物理層和協議層的兼容。在物理層,SAS接口和SATA接口完全兼容,

SATA硬碟可以直接使用在SAS的環境中,從接口標準上而言,SATA是SAS的一個子標準,因此SAS控制器可以直接操控SATA硬碟,但是SAS卻不能直接使用在SATA的環境中,

因為SATA控制器並不能對SAS硬碟進行控制;在協議層,SAS由3種類型協議組成,根據連接的不同設備使用相應的協議進行數據傳輸。

其中串行SCSI協議(SSP)用於傳輸SCSI命令;SCSI管理協議(SMP)用於對連接設備的維護和管理;SATA通道協議(STP)用於SAS和SATA之間數據的傳輸。

因此在這3種協議的配合下,SAS可以和SATA以及部分SCSI設備無縫結合。其傳輸速率比SATA要快很多。


5. 光纖通道

其為英文字母Fibre Channel的縮寫。其最初設計也不是為了硬碟設計開發的接口,是專門為網絡系統設計的,但隨著存儲系統對速度的需求,才逐漸應用到硬碟系統中。

光纖通道的主要特性有:熱插拔性、高速帶寬、遠程連接、連接設備數量大等。



6. mSATA接口

該接口是主要是用在筆記本上: 比如商務本,超極本,主流筆記本等。現在主流筆記本接口SATA接口的SATA3版本



7. M.2接口

M.2接口,是Intel推出的一種替代mSATA新的接口規範。

M.2接口是為超極本(Ultrabook)量身定做的新一代接口標準,以取代原來的mSATA接口。無論是更小巧的規格尺寸,還是更高的傳輸性能,M.2都遠勝於mSATA。

M.2接口一般分為兩種,在購買M.2 SSD的時候是需要注意內部協議的。

一種是走傳統的SATA AHCI協議,與普通SATA固態硬碟性能沒有差別;

另一種則是使用全新的NVMe協議,可以提供SSD高達3000MB/s以上的性能,可謂天差地別。



這裡著重說下固態硬碟的AHCI協議和NVMe協議

SSD(固態硬碟)最為主流的傳輸協議有兩種。一種是AHCI協議,另一種是NVMe協議。

AHCI,全稱為串行ATA高級主控接口/高級主機控制器接口,它允許存儲驅動程序啟用高級串行ATA功能。

我們在使用SATA SSD的時候,一定要在主板設置中開啟AHCI模式。

這是因為,開啟AHCI模式後,能夠大幅縮短SSD無用的尋道次數和縮短數據查找時間,這樣能讓多任務下的SSD能夠發揮全部的性能和效應。

根據相關性能測試,在AHCI模式開啟後,大約增加30%的SSD讀寫性能。

但是隨著SSD的性能逐步增強,這些標準也成為了限制固態硬碟的一大瓶頸,專為機械硬碟而設計的AHCI標準並不太適合低延時的固態硬碟。

另外一個傳輸協議,代表著未來性能走向的NVMe協議。


所謂NVMe協議,在於充分利用PCI-E通道的低延時以及並行性,,在可控制的存儲成本下,極大的提升SSD的讀寫性能,降低由於AHCI接口帶來的高延時,徹底解放SATA時代SSD的極致性能。

由於快閃記憶體顆粒和主控的原因,M.2 NVMe協議的固態硬碟價格都特別高,比SATA協議的固態硬碟高出一倍左右的價格,所以大家在選擇的時候一定要按需購買,

根據自己電腦的配置以及需求來選購相應等級的固態硬碟,不然機會造成性能浪費哦。



NVMe:眾所周知,前些年計算機的瓶頸已經從CPU\顯卡轉移到了硬盤,硬盤存取速度嚴重不足,所以SSD迅速的發展、火爆起來,

如今,SSD已經成為了圖吧、卡吧標配然而落後的SATA3接口理論上限只有6Gbps,實際很難突破800M/S,這個速度並不能滿足需求,

目前市場上的SDD很多都已經有550MB的存取速度,優秀者甚至已經突破SATA3的上限更可怕的是,SATA所遵循的AHCI標準當初是為機械硬盤涉及,

不但存取提升有限,4K方面更是不足,在IOPS和隊列深度上已經日趨拙雞。為了應對這個問題,出現了所謂的NGFF(M.2, MSATA.2)接口,利用充裕PCI-E通道,

有足夠的速度,專為超極本涉及,不但佔用空間小,省電,而且速度快,容量也不錯。而後台式機同樣出現了這個問題,就出現了SATA-Express,

原本是打算將兩個SATA口合併,6Gbps+6Gbps=12Gbps,但是最後發現如此做的話,很難達到向下兼容(如SATA3向下兼容SATA2),並且成本略高。最後又將頭緒轉向了PCI-E。


NVME是硬盤新的傳輸標準,是取代現在的AHCI的。NVMe的優勢在於三點:

1、更低的延時:  NVMe精簡了調用方式,執行命令時不需要讀取寄存器;而AHCI每條命令則需要讀取4次寄存器,一共會消耗8000次CPU循環,從而造成2.5μs的延遲。

2、更高的傳輸性能  市面上性能不錯的SATA接口SSD,在隊列深度上都可以達到32,然而這也是AHCI所能做到的極限。

   但目前高端的企業級PCIe SSD,其隊列深度可能要達到128,甚至是256才能夠發揮出最高的IOPS性能。而NVMe標準下,最大的隊列深度可達64000。

   此外,NVMe的隊列數量也從AHCI的1,提高了64000。 

3、更低的功耗控制。


NVMe:眾所周知,前些年計算機的瓶頸已經從CPU\顯卡轉移到了硬盤,硬盤存取速度嚴重不足,所以SSD迅速的發展、火爆起來,

如今,SSD已經成為了圖吧、卡吧標配然而落後的SATA3接口理論上限只有6Gbps,實際很難突破800M/S,這個速度並不能滿足需求,目前市場上的SDD很多都已經有550MB的存取速度,

優秀者甚至已經突破SATA3的上限更可怕的是,SATA所遵循的AHCI標準當初是為機械硬盤涉及,不但存取提升有限,4K方面更是不足,在IOPS和隊列深度上已經日趨拙雞。

為了應對這個問題,出現了所謂的NGFF(M.2, MSATA.2)接口,利用充裕PCI-E通道,有足夠的速度,專為超極本涉及,不但佔用空間小,省電,而且速度快,容量也不錯。

而後台式機同樣出現了這個問題,就出現了SATA-Express,原本是打算將兩個SATA口合併,6Gbps+6Gbps=12Gbps,但是最後發現如此做的話,很難達到向下兼容(如SATA3向下兼容SATA2),

並且成本略高。最後又將頭緒轉向了PCI-E。


NVME是硬盤新的傳輸標準,是取代現在的AHCI的。

NVMe的優勢在於三點:

1、更低的延時:  NVMe精簡了調用方式,執行命令時不需要讀取寄存器;

   而AHCI每條命令則需要讀取4次寄存器,一共會消耗8000次CPU循環,從而造成2.5μs的延遲。 

2、更高的傳輸性能  市面上性能不錯的SATA接口SSD,在隊列深度上都可以達到32,然而這也是AHCI所能做到的極限。

   但目前高端的企業級PCIe SSD,其隊列深度可能要達到128,甚至是256才能夠發揮出最高的IOPS性能。

   而NVMe標準下,最大的隊列深度可達64000。此外,NVMe的隊列數量也從AHCI的1,提高了64000。 

3、更低的功耗控制。

2021年9月21日 星期二

Mac install and kext 公證方式!

 


----------------------------------------

Author: Sam

Date: 2021/08/05

----------------------------------------


*******************************************************************

** ProjectMaker .mpkg 增加 Apple Sign

## productsign --sign "Developer ID Application:  User"  Source_Path  Target_Path

## productsign --sign "Developer ID Installer: User"  Source_Path  Target_Path

*******************************************************************

EX.

productsign --sign "Developer ID Application: User)" \

/Users/accusys/Desktop/Accusys_Mac_Driver_257_Beta4.mpkg \

/Users/accusys/Desktop/Accusys_Mac_Driver_257_Beta4_Sign1.mpkg



*******************************************************************

** 確認ProjectMaker .mpkg 檔案 Sign 狀態

## pkgutil --check-signature /path/to/file.pkg

*******************************************************************

EX1.

# pkgutil --check-signature Accusys_Mac_Driver_257_Beta4.mpkg 

Package "Accusys_Mac_Driver_257_Beta4":

   Status: no signature


EX2.

# pkgutil --check-signature Accusys_Mac_Driver_257_Beta4_Sign.mpkg 

Package "Accusys_Mac_Driver_257_Beta4_Sign":

   Status: signed by a certificate trusted by macOS

   Certificate Chain:

    1. Developer ID Application: User

       Expires: 2023-09-08 08:17:40 +0000

       SHA256 Fingerprint:

           ED 2E 67 F9 F1 28 70 BC DC 87 00 CA D5 99 59 B5 86 C6 69 F2 47 C7 

           A2 82 91 34 8C 58 A1 C4 4C 74

       ------------------------------------------------------------------------

    2. Developer ID Certification Authority

       Expires: 2027-02-01 22:12:15 +0000

       SHA256 Fingerprint:

           7A FC 9D 01 A6 2F 03 A2 DE 96 37 93 6D 4A FE 68 09 0D 2D E1 8D 03 

           F2 9C 88 CF B0 B1 BA 63 58 7F

       ------------------------------------------------------------------------

    3. Apple Root CA

       Expires: 2035-02-09 21:40:36 +0000

       SHA256 Fingerprint:

           B0 B1 73 0E CB C7 FF 45 05 14 2C 49 F1 29 5E 6E DA 6B CA ED 7E 2C 

           68 C5 BE 91 B5 A1 10 01 F0 24




----------------------------------------

** Apple Kext 公證方式教學

** https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow?preferredLanguage=occ

** https://juejin.cn/post/6894059183453241357

----------------------------------------

** 您的(Sam) App 專用密碼 Accusys Kext:  xxxx-xxxx-xxxx-xxxx

----------------------------------------

**

** Notarize 前準備

**

1.  先將APLLE ID 升級為 Apple ID 雙重認證.

2.  在APPLE ID 帳戶 Security 選項, 新增 APP-SPECIFIC PASSWORDS.

    這組密碼用來公證時使用的密碼.



*******************************************************************

**  選擇Xcode

##  sudo xcode-select -s /path/to/Xcode13.app

*******************************************************************

EX.

# xcode-select -s /Applications/Xcode-13beta2.app/



*******************************************************************

** Add Timestamp from kext

## codesign --timestamp -f -s "Developer ID Application: xxxx (xxxxx)" xxx.kext

*******************************************************************

EX.

# codesign --timestamp -f -s "Developer ID Application: User" ACS6x.kext

codesign -s "Developer ID Application: User" --options runtime -f --timestamp ACS6x.kext

驗證方式:

# codesign -dvvv ACS6x.kext

可以看到  "Signed Time=Jul 15, 2021 at 3:24:24 PM"

    改為  "Timestamp=Jul 15, 2021 at 3:35:21 PM"



*******************************************************************

** Add hardened runtime flag

## codesign --options=runtime --timestamp -f -s "Developer ID Application: xxxx (xxxxx)" DtrGuiSrv01_64

*******************************************************************


*******************************************************************

** Create a ZIP archive suitable for notarization.

## /usr/bin/ditto -c -k --keepParent "$APP_PATH" "$ZIP_PATH"

*******************************************************************

EX.

# ditto -c -k --keepParent /Users/accusys/Desktop/ACS6x.kext /Users/accusys/Desktop/ACS6x.kext.zip



*******************************************************************

** Notarize kext

## xcrun altool --notarize-app -f Source_path \

## --primary-bundle-id  "User_define_ID" (使用者自行定義,可用於版本區分)

## -u "Apple ID" -p "Apple ID 額外聲請第三方使用密碼"

## 成功後可以得到一組Request UUID, 等待約15分後請用查詢指令確認狀態

*******************************************************************

EX.

#xcrun altool --notarize-app -f /Users/accusys/Desktop/ACS6x.kext.zip \

--primary-bundle-id "com.Accusys.driver.368Intel" \

-u "User" -p "User"


Cmd Reply:

No errors uploading '/Users/accusys/Desktop/ACS6x.kext.zip'.

RequestUUID = 2b945190-d915-48ae-99c9-526235a7d8ec



*******************************************************************

** 確認公證狀態, 看全部資訊

## xcrun altool --notarization-history 0 --username "xxxx" --password "xxxx" 

*******************************************************************

EX.

# xcrun altool --notarization-history 0 -u "User" -p "User"


Cmd Reply:

Notarization History - page 0


Date                      RequestUUID                          Status  Status Code Status Message   

------------------------- ------------------------------------ ------- ----------- ---------------- 

2021-07-12 09:02:10 +0000 81a4299c-66d1-4016-907b-0bf53eb4432b invalid 2           Package Invalid  

2021-07-12 08:47:31 +0000 3e92f8ec-77f5-42a8-baa4-d6a6fe3b8066 success 0           Package Approved 


Next page value: 1626079651000



*******************************************************************

** 確認公證狀態, 看特定RequestUUID 細節

## xcrun altool --notarization-info "Request UUID" -u "APPLE ID" -p " App password"

## 特別注意上面附有LogFileURL, 不管對錯都可以從裡面看到相關資訊

*******************************************************************

EX1.

sh-3.2# xcrun altool --notarization-info 3e92f8ec-77f5-42a8-baa4-d6a6fe3b8066 -u "User" -p "User"

No errors getting notarization info.


          Date: 2021-07-12 08:47:31 +0000

          Hash: c3d9426297775094427e026e2fb9f423d3322dc3f79846d28deebf378fcc8813

    LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma115/v4/a7/b1/8c/a7b18cd7-dc24-0bb3-bfd0-de9ca3b701b6/developer_log.json?accessKey=1626295600_6591354106415281256_xhl7DLpqT8rtDFSq3EAx1og5tezk43VkktZ87vI%2Ba4sID7bwj7vc%2FhH9mECv7fpFMn2wp1au4z1CKOHXQ1uY91Fin%2BIEQyjF9U3dBC%2FvN18NM%2FnTVecPeyLzkRVtqpH%2B%2BfTjF4liBudo8Nuyc7V6RBOVIG8m7exygsN7PdOvQxY%3D

   RequestUUID: 3e92f8ec-77f5-42a8-baa4-d6a6fe3b8066

        Status: success

   Status Code: 0

Status Message: Package Approved


EX2.

sh-3.2# xcrun altool --notarization-info 81a4299c-66d1-4016-907b-0bf53eb4432b -u "User" -p "User"

No errors getting notarization info.


          Date: 2021-07-12 09:02:10 +0000

          Hash: 88749476df828b14a4c6f2b9de0eccf2ed605565f2bf327dcf2d208988f4d19a

    LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma115/v4/53/53/e1/5353e10a-445f-1b9c-9d88-4eef3088bb0c/developer_log.json?accessKey=1626295070_8353744305349471620_keVak2QrHUsMplR%2FuUAFQ0kASGO%2BVRlE6VTIh8VTaMe1ZX5V6ztRT3r54Nj317wTzpWfF851zAsfWeoTSNWcxOiBrHhWwfgPepzgmNVfs2WKeRqPRs%2FFaxCqOHiRv6YybiKDox2GQ1MzXEGOLG0y23sS%2B6P6DxelSgKqo3ub0J8%3D

   RequestUUID: 81a4299c-66d1-4016-907b-0bf53eb4432b

        Status: invalid

   Status Code: 2

Status Message: Package Invalid



*******************************************************************

** KEXT公證過後APPLE如何確定是否公證過, 後續需要多做一個裝訂的程序將票證裝在KEXT.

** 一旦對應用程序進行了公證,Apple便為開發人員提供了“票證”,可以將其“裝訂”到經過公證的對像上。

** 此時裝訂的過程要連接網, 由APPLE 回傳確定是否通過公證,若有則會裝訂票證到檔案.

** 如果未裝訂應用程序或kext,Internet連接下,則在加載應用程序/ kext時,macOS會使用Apple服務器簽入,以查看是否可以正常運行。

** 如果未裝訂應用程序或kext,Internet未連接下,因無法判斷是否通過公證,會直接當作無公證,導致載入時失敗.

** 具體可通過stapler工具來裝訂:

## sudo xcrun stapler staple xxxx.kext

## sudo xcrun stapler staple -v xxxx.kext 可以看詳細內容

*******************************************************************

EX.

# sudo xcrun stapler staple ACS6x.kext


Cmd Reply:

Processing: /Users/Accusys/Desktop/ACS6x.kext

The staple and validate action worked!



*******************************************************************

** 驗證是否裝訂完成 xxxxx.kext

## sudo xcrun stapler validate xxxxx.kext

## sudo xcrun stapler validate -v xxxxx.kext 可以看詳細內容

*******************************************************************

EX.

# sudo xcrun stapler validate ACS6x.kext


Cmd Reply:

The validate action worked!



*******************************************************************

** 對於APP的公證權限驗證

## spctl -a -v xxxx.app

*******************************************************************

** 對於pkg包的公證權限驗證

## spctl -v -a --type install xxx.pkg

*******************************************************************

EX1.

sh-3.2#  spctl -v -a --type install R_MacDrv_V6.2.16.pkg 

R_MacDrv_V6.2.16.pkg: accepted

source=Notarized Developer ID


EX2.

sh-3.2#  spctl -v -a --type install Accusys_Mac_BigSur_3.7.1s.mpkg/

Accusys_Mac_BigSur_3.7.1s.mpkg/: rejected

source=Unnotarized Developer ID





Mac OS Bigsur XSAN 7 cmd line 設定方式

     **  Mac OS Bigsur XSAN 7 cmd line 設定方式


    1.  設定HostName

        sh-3.2# sudo scutil --set HostName MDC.private  

    

    2.  Edit /etc/hosts 增加 HostName IP to hosts

    

        sh-3.2# cat /etc/hosts

        

        ##

        # Host Database

        #

        # localhost is used to configure the loopback interface

        # when the system is booting.  Do not change this entry.

        ##

        127.0.0.1       localhost

        255.255.255.255 broadcasthost

        ::1             localhost

        10.10.8.157     mdc.private

        

    3.  Create SAN server and account

        user : accusys

        password : accusys

        SAN_Name: Xsan

        mail : xsan@gmail.com

        certificate auth name. In this example the certificate auth name is Accusyscert

        

        " sudo xsanctl createSan SAN_Name --account user --pass password --user user --cert-auth-name  certificate_auth_name --cert-admin-email mail "

        

        sh-3.2# sudo xsanctl createSan xsan --account accusys --pass accusys --user accusys --cert-auth-name videocert --cert-admin-email xsan@gmail.com

        

        PS. "xsanctl listSan"

        xsan (mdc3.private)

        xsan (mdc.private)

        

    4.  Create an Xsan volume

        a.  export volum setting

            sh-3.2# sudo cvlabel -c >label_list

            

        b.  Edit the label_list file, changing CvfsDisk_UNKNOWN to the desired label name MetadataLUN and DataLUN:

            sh-3.2# sudo vi label_list

            From

            CvfsDisk_UNKNOWN /dev/rdisk5    # host 1 lun 0 sectors 4194285535 sector_size 512 inquiry [ACCUSYS A12S3-PS         364] serial 50363230313800003632323000000000

            CvfsDisk_UNKNOWN /dev/rdisk6    # host 1 lun 0 sectors 20971501535 sector_size 512 inquiry [ACCUSYS A12S3-PS         364] serial 50363230313800013632323000000000

            Change to 

            MetadataLUN /dev/rdisk5    # host 1 lun 0 sectors 4194285535 sector_size 512 inquiry [ACCUSYS A12S3-PS         364] serial 50363230313800003632323000000000

            DataLUN /dev/rdisk6    # host 1 lun 0 sectors 20971501535 sector_size 512 inquiry [ACCUSYS A12S3-PS         364] serial 50363230313800013632323000000000

                

        c.  Update label_list

            sh-3.2# sudo cvlabel label_list

    

            *WARNING* This program will over-write volume labels on the

                      devices specified in the file "label_list".

            

                      After execution, the devices will only be usable by the

                      Xsan. You will have to re-partition the

                      devices to use them on a different file system.

            

            

            Do you want to proceed? (Y / N) -> y

            

            /dev/rdisk5 [ACCUSYS A12S3-PS         364] unknown  Controller 'default', Serial '50363230313800003632323000000000', Sector Size 512, Sectors Max 4194285535 (2.1TB)

            

            Do you want to label it acfs-EFI - Name: MetadataLUN Sectors: 4194285535 (Y / N) -> y

            New Volume Label -Device: /dev/rdisk5  acfs Label: MetadataLUN  Sectors: 4194285535.

            

            /dev/rdisk6 [ACCUSYS A12S3-PS         364] unknown  Controller 'default', Serial '50363230313800013632323000000000', Sector Size 512, Sectors Max 20971501535 (10.7TB)

            

            Do you want to label it acfs-EFI - Name: DataLUN Sectors: 20971501535 (Y / N) -> y

            New Volume Label -Device: /dev/rdisk6  acfs Label: DataLUN  Sectors: 20971501535.

            

            Done.  2 source lines.  2 labels.

            Requesting disk rescan .

    

    

    5.  Mapping volume to Lun

        -In this example, the name of the volume is Xsan.

        -In this example, the name of the metadata LUN is MetadataLUN.

        -In this example, the name of the data LUN is DataLUN.

        Press Return after each step and if necessary, enter the administrator password.

        sh-3.2# sudo xsanctl addVolume xsan --defaultFirstPool --addLUN MetadataLUN --storagePool data --addLUN DataLUN  

        

        Verify the volume was created: sudo xsanctl list.                        

        To mount/unmount Xsan volume: sudo xsanctl mount/unmount XsanVolume      

        To remove Xsan volume: sudo xsanctl dropVolume XsanVolume                

        To stop/start Xsan volume: sudo xsanctl stopVolume/startVolume XsanVolume

        

    6.  For other client to quick setting

        Export the Xsan configuration file for other client

        sh-3.2# sudo xsanctl exportClientProfile                                                                                                        

        After you press Return, the Xsan configuration profile is saved in the current working directory. In this example, the file is named Xsan.mobilconfig.

        

    

    # Remove SAN volume 流程!

        a. Verify the volume was created:

           sh-3.2# sudo xsanctl list

        b. To mount/unmount Xsan volume:

           sh-3.2# sudo xsanctl mount/unmount XsanVolume

        c. To remove Xsan volume:

           sh-3.2# sudo xsanctl dropVolume XsanVolume

        d. stop/start Xsan volume:

           sh-3.2# sudo xsanctl stopVolume/startVolume XsanVolume

    

    

    # Remove SAN 流程!

        After you press Return, the xsanctl command creates the Open Directory and SAN.

        a. To destroy SAN:

           sh-3.2#  xsanctl destroySan Xsan

        b. To destroy Open Directory: 

           sh-3.2# xsanctl destroyMaster --account accusys --pass accusys

2021年6月22日 星期二

Mac Installer PackageMaker scripts

Mac OS 抓去 CPU 與 OS 版號資訊
CPU          `uname -m` =  x86_64 or arm64
OS 版號     `sw_vers -productVersion` = like 10.15.7


PKG安裝包的管理與文件格式分析  (參考網址)
https://zhuanlan.zhihu.com/p/24895270


PackageMaker Script 時序
preflight:點擊安裝界面上的Install按鈕時運行此腳本。該腳本在程序每次安裝時都會運行。
preinstall/preupgrade:針對單程序安裝包(pkg),該腳本會在preflight腳本運行之後運行,針對多程序安裝包(mpkg),該腳本會在用戶按下Install銨鈕後執行。
                       preinstall與preupgrade的區別:
                       preinstall只會在用戶第一次安裝該程序時執行,而preupgrade只在之前安裝過該程序,用於軟件升級時,腳本才會執行,
                       preupgrade用於軟件升級時使用。區分程序是否為第一次安裝是通過pkg安裝器Installer.app來完成的,
                       Installer.app通過查看/private/var/db/receipts目錄,查看目錄中是否有以程序包名命名的pkg文件,如果存在,說明已經安裝過,反之,為第一次安裝。
postinstall/postupgrade:該腳本在程序安裝完之後才運行。它們的區別與preinstall/preupgrade一樣。
postflight:該腳本在postinstall/postupgrade腳本之後運行。


=======================================================
postflight Sample code
=======================================================
#!/bin/sh

###
### Unloaded and Remove old driver
###
sudo kextunload /Library/Extensions/ACS6x.kext/
sudo kextunload /Library/Extensions/ACS6x.kext/
sudo kextunload /Library/Extensions/ACS6x.kext/
sudo rm -rf /Library/Extensions/ACS6x.kext

cputype=`uname -m`

if [ "$cputype" == "arm64" ]; then
  #echo "ARM    Mac OS cputyep : $cputype"
  sudo unzip /tmp/drv/ACS6x_M1.kext.zip -d /tmp/drv/
else
  #echo "Intel  Mac OS cputype : $cputype"
  sudo unzip /tmp/drv/ACS6x.kext.zip -d /tmp/drv/
fi


DRV1=/tmp/drv/ACS6x.kext
DRV2=/Library/Extensions/

sudo chown -R root:wheel     $DRV1
sudo chmod -R 755     $DRV1
sudo cp -R $DRV1 $DRV2


### restart cache for 10.15/11.00 with m1 issue
#sudo kmutil clear-staging

### Remove temp file
sudo rm -rf /tmp/drv

exit 0 

=======================================================
postflight Sample code
=======================================================
#!/bin/sh

###
### Remove old version before install file
###
sudo rm -rf /System/Library/Extensions/ACS62000.kext
sudo rm -rf /System/Library/Extensions/ACS6xxxx.kext
sudo rm -rf /System/Library/Extensions/Accusys6xxxx.kext
sudo rm -rf /System/Library/Extensions/ACS6x.kext
sudo rm -rf /Library/Extensions/ACS6x.kext
sudo rm -rf /System/Library/Extensions/AccusysNTDevice.kext

### Update driver
OSver=`sw_vers -productVersion`
OSver1=$(echo $OSver | cut -d "." -f 1)
OSver2=$(echo $OSver | cut -d "." -f 2)
OSver=$OSver1.$OSver2
#echo "Check Mac OS kernel version: OS version : $OSver"

if [ $(echo "$OSver >= 10.10" |bc) -eq 1 ]; then
      #echo " > Check Mac OS kernel version: Darwin kernel version : $OSver"
      DRV1=/tmp/drv/ACS6x.kext
      DRV2=/Library/Extensions/
else
      #echo " < Check Mac OS kernel version: Darwin kernel version : $OSver"
  DRV1=/tmp/drv/ACS6x.kext
  DRV2=/System/Library/Extensions/
fi

sudo chown -R root:wheel $DRV1
sudo chmod -R 755 $DRV1
sudo cp -R $DRV1 $DRV2

if [ $(echo "$OSver >= 10.9" |bc) -eq 1 ]; then
  sudo kextcache -system-caches
else
  sudo touch  /System/Library/Extensions 
fi

### Remove temp file
sudo rm -rf /tmp/drv

exit 0
=======================================================

2020年11月4日 星期三

Linux rpm build (3) .service 開機可自動執行

參考來源:

Linux systemd 系統服務管理基礎教學與範例

如何在Linux上將任意應用程式變成開機可自動執行


Systemd 基本服務管理

在 Systemd 中每一個系統服務就稱為一個服務單位(unit),而服務單位又可以區分為 service、socket、target、path、snapshot、timer 等多種不同的類型(type),

我們可以從設定檔的附檔名來判斷該服務單位所屬的類型,最常見的就是以 .service 結尾的系統服務,大部分的伺服器都是屬於這種。


如果要管理 Systemd 中的各種服務,可以使用 systemctl 這個指令,配合各種操作指令來進行各種操作。


systemctl 操作指令 服務名稱.service

若要啟動系統服務,可以使用 start 操作指令,例如啟動 accusys.service:

當我們在指定服務名稱時,可以將結尾的 .service 省略,這樣可以少打一些字,例如:


# 套用Systemd Unit的設定檔變更

在新增、或是修改Systemd Unit的設定檔後,要在終端機執行以下指令才會重新載入:

sudo systemctl daemon-reload


# 啟動 service

sudo systemctl start accusys


# 顯示 service 服務狀態

systemctl status accusys


# 停止 service 服務

sudo systemctl stop accusys


# 設定開機自動啟動 service

sudo systemctl enable accusy


# 取消開機自動啟動 service

sudo systemctl disable accusys


# 檢查 service 服務是否正在運行

systemctl is-active accusys


# 檢查 service 服務是否有設定開機自動啟動

systemctl is-enabled accusys


# 檢查 service 服務是否啟動失敗

systemctl is-failed accusys


列出 Systemd 所有服務

若想要列出所有已啟動的服務,可以使用 list-units 操作指令:


# 列出所有已啟動的服務

systemctl list-units


# 查看服務內部設定檔

systemctl cat accusys.service


---------------------------------------------------------------->

[Unit]

Description=Accusys GUI GS

After=network.target

 

[Service]

# User=user

# Group=group

# WorkingDirectory=/path/to/folder

ExecStart=/lib/modules/3.10.0-514.el7.x86_64/kernel/drivers/scsi/accusys/RGX_GS_3.6.8/DTRGuiSrv_64

Restart=always

RestartSec=10s


# Environment="VARIABLE_1=VALUE_1" "VARIABLE_2=VALUE_2"

# Environment="VARIABLE_3=VALUE_3" "VARIABLE_4=VALUE_4"

 

[Install]

WantedBy=multi-user.target

<----------------------------------------------------------------


[Unit]區塊中,我們撰寫了兩個項目。

Description用來設定這個Systemd Service Unit設定檔案的描述,可以讓管理員在日後查看時還能想起這個Systemd Service Unit的目的是什麼。

另一個After項目可以用來指定一個Systemd Target Unit,可以確保目前正在設定的這個Unit,會在Systemd Target Unit運行完後再運行。

如果是用來提供Web服務的應用程式,那麼通常就必須要在作業系統環境的網路功能被啟用之後才能夠正常啟動,

所以After項目設定為network.target可以確保該程式在第一次執行時候就順利啟動。


[Service]區塊中有五個使用井字號#註解掉的項目,這些先不要管它,稍候會再提到。

ExecStart項目可以用來設定當這個Systemd Service Unit項目啟動時要執行的應用程式(需使用完整絕對路徑),並且如果需要的話,

可以利用空白字元來分隔多個不同的引數。若是這個程式需要搭配shell的命令列功能(例如變數、管線等)來執行,

那就使用如以下的方式先執行shell之後,再運行shell的命令吧!


ExecStart=/bin/bash -c 'shell命令'

Restart項目可以設定ExecStart所執行的程式要在什麼樣的情況被關閉時,以相同的指令再重新執行一次。有效的設定值如下:


no:不重啟。(預設值)

always:不管什麼原因都會重啟。

on-success:只在成功運行結束後(也就是行程回傳的Exit Status為0的時候)才進行重啟。(這蠻少用)

on-failure:在運行失敗後(行程回傳的Exit Status非為0、被使用Kill信號強制關閉、逾時或是餵狗沒反應時)才進行重啟。

on-abnormal:在意外地運行失敗後(被使用Kill信號強制關閉、逾時或是餵狗沒反應時)才進行重啟。

on-abort:被使用Kill信號強制關閉時才進行重啟。

on-watchdog:餵狗沒反應時才進行重啟。

上述提到的「逾時」,可以在[Service]區塊中用TimeoutSec項目來設定程式在執行多久後算是逾時,一般我們是用不到這個機制啦!

而「餵狗」則是使用Systemd提供的看門狗(Watchdog)機制,使程式在固定時間內(可以在[Service]區塊中用WatchdogSec項目來設定),

必須主動呼叫Systemd函式庫的sd_notify函數,以利Systemd判斷該程式是否還是正常運作的狀態,一般我們也是用不到這個機制的啦!


至於RestartSec這個項目,就是設定程式在被關閉後,到下次自動重啟的間隔時間,預設是100ms(毫秒)。

最後的[Install]區塊中,只有WantedBy這一個設定項目,它可以用來指定一個Systemd Target Unit,讓目前正在設定的這個Unit,

會在運行該Systemd Target Unit時,也跟著被運行。

接著來談談被註解掉的項目,首先是User和Group這兩個項目,它們可以分別用來設定要運行ExecStart項目所指定的程式時所使用的使用者名稱和群組名稱。

另外如果程式的運行必須仰賴工作目錄的支援的話,就要使用WorkingDirectory項目來手動指定程式工作目錄的路徑。

而如果要替執行的程式設定環境變數的話,可以透過一個或是數個Environment項目來設定,一個Environment項目可以設定多個環境變數。



Linux rpm build (2) - RPM 如何打包

相關參考網址:

RPM 打包︰由一竅不通到動手濫用

RPM打包原理、示例、詳解及備查


** rpmbuild 建置指令

rpmbuild -bb accusys.spec


** 撰寫 rpm SPEC

---------------------------------------------------------------->

# Some metadata required by an RPM package

Name: accusys

Summary: Install Accusys linux driver and GUI.

Version: 1.0

Release: 1

License: GPLv2


%description

Install Accusys driver for "DaVinci-Resolve-Linux-16.0-CentOS_7.3"

Install Accusys GUI GC and GS.


# Get the kernel headers version installed, not based on uname.

%define kversion %(rpm -q kernel%{?bt_ext}-devel | sort --version-sort | tail -1 | sed 's/kernel%{?bt_ext}-devel-//')

%define RGX_GC RGX_GC_3.6.8

%define RGX_GS RGX_GS_3.6.8


%install

mkdir -p %{buildroot}/lib/modules/`uname -r`/extra/accusys

cp -pdf /home/Sam/rpmbuild/SOURCES/ACS6x.ko %{buildroot}/lib/modules/`uname -r`/extra/accusys/ACS6x.ko

chmod 755 %{buildroot}/lib/modules/`uname -r`/extra/accusys/ACS6x.ko

cp -pdfr /home/Sam/rpmbuild/SOURCES/%{RGX_GS} %{buildroot}/lib/modules/`uname -r`/extra/accusys/%{RGX_GS}

cp -pdfr /home/Sam/rpmbuild/SOURCES/%{RGX_GC} %{buildroot}/lib/modules/`uname -r`/extra/accusys/%{RGX_GC}

mkdir -p %{buildroot}/usr/lib/systemd/system

cat <<EOF> %{buildroot}/usr/lib/systemd/system/accusys.service

[Unit]

Description=Accusys GUI GS

After=network.target

 

[Service]

# User=user

# Group=group

# WorkingDirectory=/path/to/folder

ExecStart=/lib/modules/3.10.0-514.el7.x86_64/extra/accusys/RGX_GS_3.6.8/DTRGuiSrv_64

Restart=always

RestartSec=10s


[Install]

WantedBy=multi-user.target

EOF


%post

depmod

systemctl start accusys

systemctl status accusys

systemctl enable accusys


%preun

systemctl stop accusys

systemctl disable accusys


%postun

depmod


%files

/lib/modules/%{kversion}/extra/accusys/ACS6x.ko

/lib/modules/%{kversion}/extra/accusys/%{RGX_GS}

/lib/modules/%{kversion}/extra/accusys/%{RGX_GC}

/usr/lib/systemd/system/accusys.service

<----------------------------------------------------------------


SPEC 檔︰ 參數定義


** SPEC 檔︰表頭 (Preamble) 的基本內容

Name:           所包裝軟件的名稱。

Summary:        軟件的簡短介紹。

Version:        軟件的版本編號。

Release:        同一版本軟件的發佈次數。預設為 1%{?dist},每打包一次應該 +1,直到版本編號更新為止。

License:        軟件的使用授權模式,像是「GPLv3」或者「MIT」之類。


URL:            軟件的官方網站。

Source0:        下載軟件源代碼的路徑或完整網址。如果有多於一個,可繼續用 Source1, Source2, … SourceX 去定義。

Patch0:         下載第一個源代碼補丁的網址。只在有需要時定義。同樣可以有 Patch1, Patch2, … PatchX。

BuildArch:      如果只支援在特定硬體架構編譯,需要在這裏定義,像是「x86_64」之類。

BuildRequires:  定義編譯軟件所需要的套件。需要用逗號或空白分隔套件名稱,亦可以分開多次定義 BuildRequires。

Requires:       定義執行軟件所需要的套件。需要用逗號或空白分隔套件名稱,亦可以分開多次定義 BuildRequires。

ExcludeArch:    如果軟件不能在特定架硬件架構下運作,需要在此定義。


** SPEC 檔︰內文 (Body) 的基本內容

%install:       安裝編譯好軟件的 shell 程序。一般包括將你要安裝的執行檔、軟件庫、設定檔、說明文件等等,

                由編譯的資料匣(如 %_builddir)移放到 %buildroot 去。

                在理想的世界裏,是預備好 ~/rpmbuild/BUILDROOT 的資料匣結構,然後把檔案由 ~/rpmbuild/BUILD 搬到 ~/rpmbuild/BUILDROOT 的程序。

%check:         檢查軟件的 shell 程序,一般擺放 unit test 的指令。

%files:         需要打包的檔案列表,每行一個定義,可以使用 bash 通用的「*」萬用字元 。

                留意這裏的檔案路徑以 %buildroot 定義的資料匣為根目錄,換言之沒放在這裏的檔案,是無法被打包的。

%changelog:     軟件變化的紀錄,定義不同版本 (version) 或建置版本 (build) 的變化。


在軟體包安裝之前( %pre)或之後( %post)執行

在軟體包卸載之前( %preun)或之後( %postun)執行

在事務開始( %pretrans)或結束( %posttrans)時執行















2020年11月3日 星期二

Linux rpm build (1) - rpmbulid

    rpm命令使用簡介

    什麼是rpm?

    rpm是RPM package manager的縮寫,最早由RedHat公司提出的軟體包標準,後來隨著rpm的不斷髮展而又增加許多功能,

    逐漸的成為linux公認的軟體包管理標準。支援該格式的廠商有RedHat linux、suse linux、Mandriva linux。


    rpm命令十分強大,那麼rpm命令究竟有什麼功能呢?

    1 查詢已安裝在linux系統中的rpm軟體包的資訊

    2 查詢rpm軟體包安裝檔案的資訊

    3 安裝rpm軟體包到當前linux系統

    4 從linux系統中解除安裝已安裝的rpm軟體包

    5 升級當前linux系統的rpm軟體包

    (1)#rpm -qa       後面不接引數用於檢視系統中已經安裝的所有的rpm

    (2)#rpm -q rpm    用於檢視系統中是否安裝了該軟體包,如果安裝了,系統會顯示完整的包名;如果沒有安裝,系統會提示”package bas is not installed”。

    (3)#rpm -qi rpm   用於檢視系統中已經安裝的rpm包的完整資訊,包括該包的版本資訊,安裝時間和大小等。

    (4)#rpm -ql rpm   用於檢視該軟體包都安裝到了那些位置。

    (5)#rpm -qf 檔名  用於檢視某個檔案使用那個rpm包安裝的。

    (6)#rpm -qpi rpm  和#rpm -qpl分別用於檢視沒有安裝的包的資訊,注意下和(4)、(5)的區別。

    (7)#rpm -ivh      用於安裝rpm軟體包,i代表安裝、v代表視覺化安裝、h代表安裝的時候顯示進度。

    (8)#rpm –force -irpm 用於強制安裝rpm軟體包,–force引數用於安裝存在依存關係的rpm包。不過一般我們並不怎做,解決依存關係的較好的方法是使用#rpm -i 命令一起安裝。

    (9)#rpm -e rpm    用於刪除rpm軟體包。

              #rpm -e –nodeps rpm 用於刪除存在依存關係的軟體包,該命令可以將和該包存在依存關係的所有的軟體包統統刪除。

   (10)#rpm -Urpm     用於對rpm包的升級。


    **解壓縮rpm檔

    在 Redhat 系列的發行版內, 所有安裝的套件都會打包成 rpm 檔, 安裝時只要安裝一個檔案便可以, 就如同 Debian 的 deb 檔,

    使用 rpm 安裝套件十分方便, 但有時只想解開 rpm 檔的內容, 而不要安裝套件, 這時可以用 rpm2cpio cpio 指令。

    解開 rpm 不像解開 deb 可以用單一指令完成, 需要先用 rpm2cpio 轉換 rpm 成為 cpio 格式, 再用 cpio 解開,

    這個動作可以透過管線 (pipe) 完成。

    例如有一個 example.rpm 要解開, 指令是這樣:

    # rpm2cpio example.rpm | cpio -idmv

    以上指令會將 example.rpm 的內容解開到當前目錄。


    ** rpmbuild  手動建立自己的rpm

    動手打包前,首先得安裝相關的軟件。我們需要使用的程式是 rpmbuild

    如果你是 RHEL、CentOS

    sudo yum install rpm-build


    如果你是 Ubuntu 或者 Debian 的用戶,

    sudo apt-get install rpm

    

    安裝之後,我們來試一試 rpmbuild是否存在︰

    rpmbuild --version

    RPM version 4.4.2.3



文章參考:

https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC/392870/

https://www.opencli.com/linux/extract-rpm-files

 

2020年7月23日 星期四

How to compile Kernel Ubuntu 20.04


Copy from https://linuxguides.co.uk/guides/how-to-compile-kernel-ubuntu-20-04/

How to compile Kernel Ubuntu 20.04


In this guide I am going to show you how to compile a Kernel on Ubuntu 20.04 x86_64
First of all we are going to install the missing dependencies
apt-get update && apt-get upgrade && apt-get install -y build-essential libncurses5-dev gcc libssl-dev grub2 bc bison flex libelf-dev
Then we are going to download the kernel from kernel.org
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.7.5.tar.xz
tar -xvf linux-5.7.5.tar.xz
Then we need to copy the existing config file so that the correct modules for the Hardware of the machine you are compiling the kernel for
You need to enter the command below to find the current kernel config file.
ls -l /boot
cp /boot/config-4.4.0-21-generic /root/linux-5.7.5/.config
Then we are going to compile the kernel firstly you want to cd into the kernel folder
cd /root/linux-5.7.5
(Adjust -j8 to the amount of cores the machine has that you are compiling the kernel for)
make menuconfig
make -j8 deb-pkg
dpkg -i ,,/linux-*.deb
update-grub
Then you can proceed to rebooting the machine by typing the following
reboot
Once the machine is rebooted you can confirm the latest kernel by entering the following command
uname -a

2020年6月11日 星期四

Mac loaded driver script

#!/bin/bash
 
# MacOS Catalina (10.15):  Darwin 19.x.0
kernelver=`uname -a | awk '{print $3}'`
kernelver1=$(echo $kernelver | cut -d "." -f 1)
kernelver2=$(echo $kernelver | cut -d "." -f 2)
kernelver=$kernelver1.$kernelver2
echo "Check Mac OS kernel version: Darwin kernel version : $kernelver"


if [ $(echo "$kernelver >= 19.0" |bc) -eq 1 ]; then
    echo "  Mac OS version >= 10.15.x"
   
    kernelpath=`sudo pwd`
    if [ "$kernelpath" != "/Library/Extensions" ]; then
        echo "  In path $kernelpath"
        if [ -d "/Library/Extensions/ACS6x.kext" ]; then
            # 目錄 存在
            echo "  Directory /Library/Extensions/ACS6x.kext exists."
           
            echo "  Remove ACS6x.kext driver"
            sudo rm -rf /Library/Extensions/ACS6x.kext
           
            echo "  Copy driver to system"
            sudo cp -R ACS6x.kext /Library/Extensions/
            sudo cd /Library/Extensions/
           
        else
            # 目錄 不存在
            echo "  Directory /Library/Extensions/ACS6x.kext does not exists."
           
            echo "  Copy driver to system"
            sudo cp -R ACS6x.kext /Library/Extensions/
            sudo cd /Library/Extensions/
        fi
       
    else
        if [! -d "/Library/Extensions/ACS6x.kext" ]; then
            # 目錄 不存在
            echo "  Error: Directory /Library/Extensions/ACS6x.kext does not exists."
            exit 0
        fi
       
    fi
   
    echo "  Change ACS6x.kext driver owner"
    sudo chmod -R 755 ACS6x.kext
    sudo chown -R root:wheel ACS6x.kext
    sudo xattr -d -r ACS6x.kext
   
    driverstat=`sudo kextstat|grep Accusys`
    if [ "$driverstat" != "" ]; then
        echo "  Kextunload ACS6x.kext driver"
        sudo kextunload ACS6x.kext
        sudo kextunload ACS6x.kext
    fi
   
    echo "  Clear system cache"
    sudo kextcache -clear-staging
   
    echo "  Loaded ACS6x.kext driver"
    sudo kextload ACS6x.kext
   
    echo "  Rebiuld system cache"
    #sudo kextcache -system-prelinked-kernel
    #sudo kextcache -system-caches
    sudo kextcache -i /

else
    echo "Mac OS version < 10.15.x"
   
    driverstat=`sudo kextstat|grep Accusys`
    if [ "$driverstat" != "" ]; then
        echo "  Kextunload ACS6x.kext driver"
        sudo kextunload ACS6x.kext
        sudo kextunload ACS6x.kext
    fi
   
    echo "Kextload ACS6x.kext driver"
    sudo chmod -R 755 ACS6x.kext
    sudo chown -R root:wheel ACS6x.kext
    sudo kextload ACS6x.kext
   
    if [ $(echo "$kernelver >= 14.0" |bc) -eq 1 ]; then
        sudo touch /Library/Extensions
    else
        sudo touch /System/Library/Extensions
    fi
   
fi

2020年6月9日 星期二

Linux grep 用法

*** 用‘grep’搜索文本文件
    如果您要在幾個文本文件中查找一字符串,可以使用‘grep’命令。‘grep’在文本中搜索指定的字符串。
    假設您正在‘/usr/src/linux/Documentation’目錄下搜索帶字符串‘magic’的文件:
 
    $ grep magic /usr/src/linux/Documentation/*
    sysrq.txt:* How do I enable the magic SysRQ key?
    sysrq.txt:* How do I use the magic SysRQ key?
 
    其中文件‘sysrp.txt’包含該字符串,討論的是 SysRQ 的功能。
 
    默認情況下,‘grep’隻搜索當前目錄。如果此目錄下有許多子目錄,‘grep’會以如下形式列出:
 
    grep: sound: Is a directory
 
    這可能會使‘grep’的輸出難於閱讀。這裡有兩種解決的辦法:
 
    明確要求搜索子目錄:grep -r
    或忽略子目錄:grep -d skip
    當然,如果預料到有許多輸出,您可以通過 管道 將其轉到‘less’上閱讀:
 
    $ grep magic /usr/src/linux/Documentation/* | less
 
    這樣,您就可以更方便地閱讀。
    有一點要注意,您必需提供一個文件過濾方式(搜索全部文件的話用 *)。如果您忘了,‘grep’會一直等著,直到該程序被中斷。如果您遇到了這樣的情況,按 ,然後再試。
 
 
    命令行參數:
    grep -i pattern files :不區分大小寫地搜索。默認情況區分大小寫,
    grep -l pattern files :隻列出匹配的文件名,
    grep -L pattern files :列出不匹配的文件名,
    grep -w pattern files :隻匹配整個單詞,而不是字符串的一部分(如匹配‘magic’,而不是‘magical’),
    grep -C number pattern files :匹配的上下文分別顯示[number]行,
    grep pattern1 | pattern2 files :顯示匹配 pattern1 或 pattern2 的行,
    grep pattern1 files | grep pattern2 :顯示既匹配 pattern1 又匹配 pattern2 的行。


*** grep OR
    以下幾種方法,也可以實現 or 搜索,會對兩種字串進行搜索,只要符合其中一個條件,即會印出那行的內容:
    $ grep ‘pattern1\|patten2’ file.txt
    $ grep -E ‘pattern1|pattern2’ file.txt
    $ egrep ‘pattern1|pattern2’ file.txt
    $ grep -e pattern1 -e pattern2 file.txt

*** grep AND
    $ grep -E ‘pattern1.*pattern2’ file.txt
    $ grep -E ‘pattern1.*pattern2|pattern2.*pattern1’ file.txt
    $ grep -e pattern1 -e pattern2 file.txt


*** grep 要看前兩行或後一行的資訊,該怎麼找呢?

    $ grep -A1 -B2 "5_keyword" file.txt
    3
    4
    5_keyword
    6
 
    grep 參數說明 OPTIONS
    -A NUM, --after-context=NUM  從關鍵字點往後顯示 NUM 行數
       Print NUM lines of trailing context after matching lines. Places a line containing -- between con-
       tiguous groups of matches.
    -B NUM, --before-context=NUM 從關鍵字點往前顯示 NUM 行數
       Print NUM lines of leading context before matching lines. Places a line containing -- between con-
       tiguous groups of matches.
 
 
*** grep 參數說明 OPTIONS
    -n:顯示行數,顯示關鍵字在文件的第幾行出現
    --color=auto:顯示顏色,顯示符合字串的特徵會以顏色來表示
 
    例:dmesg | grep -n -A3 -B2 --color=auto sda
 
*** 用‘grep’搜索文本文件
    如果您要在幾個文本文件中查找一字符串,可以使用‘grep’命令。‘grep’在文本中搜索指定的字符串。
    假設您正在‘/usr/src/linux/Documentation’目錄下搜索帶字符串‘magic’的文件:
 
    $ grep magic /usr/src/linux/Documentation/*
    sysrq.txt:* How do I enable the magic SysRQ key?
    sysrq.txt:* How do I use the magic SysRQ key?

*** find /usr/local/ -name "*.php" -exec grep -l 'function do_action' {} \;

    /usr/local 要尋找的路徑
    *.php 要尋找的檔案類型
    -exec 找到符合的檔案後接著執行那個指令
    -l 顯示檔路路徑
    function do_action 檔案內容有這個keyword的檔名
 
*** 如何殺死defunct殭屍程序
    ps aux | grep defunct ,如果程序為defunct
    ps -ef | grep defunct | grep -v grep | awk '{print "kill -9 " $2,$3}'  //PS. $2 PID $3 PPID

*** linux下find與grep管道命令的組合使用:

    ** 使用find與grep
    
    1.查找所有".h"文件(非組合命令)
    find /PATH -name "*.h"
    
    2.查找所有".h"文件中的含有"helloworld"字符串的文件(組合命令)
    find /PATH -name "*.h" -exec grep -in "helloworld" {} \;
    find /PATH -name "*.h" | xargs grep -in "helloworld"
    
    3. 查找所有".h"和".c"文件中的含有"helloworld"字符串的文件
    find /PATH /( -name "*.h" -or -name "*.c" /) -exec grep -in "helloworld" {} \;
    
    4. 查找非備份文件中的含有"helloworld"字符串的文件
    find /PATH /( -not -name "*~" /) -exec grep -in "helloworld" {} \;
    注:/PATH為查找路徑,默認為當前路徑。帶-exec參數時必須以\;結尾,否則會提示“find:遺漏“-exec”的參數”。
    
    ** 使用find和xargs
    
    1. find pathname -options [-print -exec -ok]
    -optinos
    1)-name:按照文件名查找
        find ~ -name “*.txt” -print
        find ~ -name “[az][0-9]. txt” -print
    2)-perm:按照權限查找文件
        find ~ -perm 755 -print查找權限為755的文件
        find ~ -perm 007 -print查找o位置上具有7權限的文件
        find ~ -perm 4000 -print查找具有suid的文件
    3)-prune
        不在當前目錄下查找
    4)-user和-nouser
        find ~ -user zhao -print查找文件屬主是zhao的文件
        find ~ -nouser -print查找文件屬主已經被刪除的文件
    5)-group和-nogroup
        find ~ -group zhao -print查找文件群組是zhao的文件
    6)按照時間
        find ~ -mtime -5 -print文件更改時間在5天內的文件
        find ~ -mtime +3 -print文件更改時間在3天前的文件
        find ~ -newer file1 -print查找比文件file1新的文件
    7)按照類型查找
        find ~ -type d -print查找所有目錄
    8)按照大小
        find ~ -size +1000000C -print查找文件大小大於1000000字節(1M)的文件
    9)查找位於本文件系統裡面的文件
        find / -name “* .txt” -mount -print
        -exec,-ok:find命令對於匹配文件執行該參數所給出shell命令,相應命令形式為: 'command' {} \;
        -ok在執行命令前要確認
        find ~ - type f -exec ls -l {} \;
        find / -name “*.log” -mtime +5 -ok rm {} \;
        find . -name core -exec rm {} \;
        使用-x dev參數    防止find搜索其他分區
        find . -size 0 -exec rm {} \;
        刪除尺寸為0的文件
    2. xargs與-exec功能類似
        find ~ -type f | xargs ls -l
        find / -name “*.log” -type f -print| xargs grep -i DB0
        find . -type f |xargs grep -i “Mary”
        在所有文件中檢索字符串Mary
        ls *~ |xargs rm -rf
        刪除所有以~結尾的文件
     
    
    ** svn過濾svn文件夾
    
    1.使用管道進行雙層“過濾”,其中第二次grep使用了-v選項,即逆向匹配,打印出不匹配的行
        grep -r ' function_name ' * | grep -v '.svn'
     
    2.或者更簡單一些,直接使用--exclude-dir選項,即指定排除目錄,注意svn前的  \.
        grep -r --exclude-dir=\.svn 'function_name' * 
        grep多個過濾條件
    
    1、or操作
      grep -E '123|abc' filename //找出文件(filename)中包含123或者包含abc的行
      egrep '123|abc' filename //用egrep同樣可以實現
      awk  '/123|abc/' filename // awk的實現方式
    
    2、and操作
      grep pattern1 files  |  grep pattern2 :顯示既匹配pattern1又匹配pattern2的行。
    
    3、其他操作
    grep  - i pattern files :不區分大小寫地搜索。默認情況區分大小寫,
    grep  - l pattern files :只列出匹配的文件名,
    grep  - L pattern files :列出不匹配的文件名,
    grep  - w pattern files :只匹配整個單詞,而不是字符串的一部分(如匹配'magic',而不是'magical'),
    grep  - C number pattern files :匹配的上下文分別顯示[ number ]行,

find / -name Info.plist -exec grep -i "Accusys" {} \;
    

 
 

2020年5月29日 星期五

linux irqbalance setting

[Ubuntu] 關閉 停用 irqbalance

關閉 停用 irqbalance

編輯 ~# vi /etc/default/irqbalance 修改以下設定:
# 找到下面這行設定
#ENABLED="1"
# 更改設定為0
ENABLED="0"


關閉 irqbalance 服務
~# service irqbalance stop
irqbalance stop/waiting

2020年5月27日 星期三

Mac log 查看

log show --predicate 'processImagePath contains "kernel"' --style syslog --last 1d
log
usage:
    log <command>

global options:
    -?, --help
    -q, --quiet
    -v, --verbose

commands:
    collect         gather system logs into a log archive
    config          view/change logging system settings
    erase           delete system logging data
    show            view/search system logs
    stream          watch live system logs
    stats           show system logging statistics

further help:
    log help <command>
    log help predicates
log config is mainly aimed at developers, although it may sometimes be useful if you are trying to solve a problem in a specific app.

log erase (which I suspect also requires sudo) is probably more damaging than useful.

log stream is for prospective collection, one of the few things that Console 1.0 does well.

This leaves the log show command, which is of greatest use for historical data. Although it does support some other options, for our purposes this will normally be used with the following:
log show --predicate [] --style syslog --start [] --end [] --info --last []
where [] represent values which we supply. I’ll take each of those options in turn.

--predicate filters the log content according to the criteria supplied, as predicates. At a simple level, these are straightforward, but can get elaborate and at times confusing. The main types of predicate which you are likely to use are:

eventMessage, as in eventMessage contains "launchd", which selects entries where the message content contains the string launchd
messageType, as in messageType == error, which selects entries which are classified as errors
processID, as in processID < 100, which selects entries from processes with IDs less than 100, i.e. early and low-level
subsystem, as in subsystem == "com.apple.TimeMachine", which selects entries for that specified ‘subsystem’. One neat way to discover subsystems is to use Console 1.0’s info panel; select a log entry and it will give you the applicable subsystem. You will also note how many important processes are not associated with subsystems, which limits the value of this predicate
eventType, processImagePath, senderImagePath, and category are also described in the man page, but so far I have seen little use for them.
You can combine predicates using and or &&, and or, according to Cocoa’s predicate-based filtering.

--style is omitted if you want the output in full form, set to syslog for more compact text form, or to json if you want JSON which you can parse into other software (a powerful feature).

--start and --end set starting and finishing dates and times for the log extraction, given in standard UTC format. These are very valuable for limiting the amount of output, but you will then have to work out the correct values to use.

--info shows all messages down to info level, which is ideal for most purposes.

--last specifies a period of log to extract, for the last minutes, hours, or days, e.g. 3m for 3 minutes, 2h for 2 hours, or 1d for one day. This is an alternative to giving start and end times.

The output from log show is often then piped through additional tools such as grep and cut, and may then be poured into a text file. We shall see these in examples below.

Example commands

John Galt’s suggested command to inspect log entries for Time Machine backups is:
log show --predicate 'subsystem == "com.apple.TimeMachine"' --info | grep 'upd: (' | cut -c 1-19,140-999

This filters log entries to those for the Time Machine subsystem, and accesses them down to info level. That output is passed through grep to extract only those entries containing the string ‘upd: (‘, and then cuts out a chunk of text from the middle of each line. Note how the predicate is given inside single quotes, to ensure that the command line copes with its spaces properly.

An alternative which just captures the last couple of backups might be
log show --predicate 'subsystem == "com.apple.TimeMachine"' --style syslog --info --last 3h | cut -c 1-22,43-999

This uses the same predicate, but works on the syslog format output, and only uses log entries over the last 3 hours. The final cut gives a slightly different layout.

If you want to look in detail at a relatively short section of log, use
log show --style syslog --start '2016-09-30 06:58:10' --end '2016-09-30 06:59:00' --info

This does not use a predicate filter, so will result in many log entries, but does restrict the time window. Note that the dates and times are given in single quotes to ensure that they are properly handled.

To capture just the errors logged over a period, try something like
log show --predicate 'messageType == error' --style syslog --start '2016-09-30 06:58:10' --end '2016-09-30 06:59:00' --info | cut -c 1-22,43-999
or, to capture just those over the last minute,
log show --predicate 'messageType == error' --style syslog --info --last 1m | cut -c 1-22,43-999

Bear in mind that the logs can contain 70,000 or more entries in any given minute, so these could still be very hefty log excerpts.

Here are the two commands to create an empty text file, and then dump a short log extract to it:
touch ~/Documents/logrestart.text
(which creates the empty file, and)
log show --start '2016-09-30 06:58:10' --end '2016-09-30 06:59:50' --info > ~/Documents/logrestart.text
which then extracts the log excerpt into that text file, ready for you to browse.

Strategies

Here are some suggestions as to how you can use these commands in common situations.

To check your Time Machine backups, you can use either of the commands above,
log show --predicate 'subsystem == "com.apple.TimeMachine"' --info | grep 'upd: (' | cut -c 1-19,140-999
or
log show --predicate 'subsystem == "com.apple.TimeMachine"' --style syslog --info --last 3h | cut -c 1-22,43-999

If you’d prefer to put their output into a text file rather than the Terminal window, create the file first using
touch ~/Documents/logtmbackups.text
then pipe log’s output into that
log show --predicate 'subsystem == "com.apple.TimeMachine"' --style syslog --info --last 1d | cut -c 1-22,43-999 > ~/Documents/logtmbackups.text

To look for a startup entry,
log show --predicate 'eventMessage contains "BOOT_TIME"' --style syslog --info | cut -c 1-22,43-999

To look for a system waking up,
log show --predicate 'eventMessage contains "System Wake"' --style syslog --info | cut -c 1-22,43-999

You can then look at errors immediately before and after that date and time, e.g.
log show --predicate 'messageType == error' --style syslog --start '2016-09-30 06:57:10' --end '2016-09-30 06:59:00' --info | cut -c 1-22,43-999
and if that doesn’t tell you what went wrong, try dumping that window into a text file and browsing through it, with
touch ~/Documents/logrestart.text
log show --start '2016-09-30 06:57:10' --end '2016-09-30 06:59:00' --info > ~/Documents/logrestart.text

To look for error messages from an app, you will need to discover that app’s identifier, such as com.company.product. Then roll that into a command like
log show --predicate '(messageType == error) and (subsystem == "com.company.product")' --style syslog --info | cut -c 1-22,43-999

If you come up with some neat log commands, and solutions, please share them here. My next task is to package these into something which doesn’t require Terminal, so that I can send tools out to those whose problems I am trying to diagnose. I will make those tools available here.

2020年4月28日 星期二

修正Mac當機後不要直接重開機

Adjust Whether a Mac Restarts Automatically on System Freeze

sudo systemsetup -getrestartfreeze

You’ll either see one of two reports, indicating the status of the feature:

Restart After Freeze: On

or:

Restart After Freeze: Off

Again, the default Mac setting now is to be “On” – it is highly recommended to leave that setting enabled as is and not adjust it.

Adjusting the Automatic Mac Restart Upon Freeze Feature
If you’re advanced user and you wish to toggle the auto-restart on freeze feature, the following command syntax will do so. Adjust the ‘on’ or ‘off’ component of the command to achieve the desired effect:

Turn automatic restarting upon freeze on:

sudo systemsetup -setrestartfreeze on

Turn automatic restarting upon freeze off:

sudo systemsetup -setrestartfreeze off

Keep in mind if you turn this feature off, an unattended frozen Mac will stay frozen at whatever is on screen for however long it takes a user to come an force the computer to reboot, if not for some other power event taking place. This is one of many reasons why the average user should leave the setting turned on.

Even with the automatic restart on freeze feature left enabled, sometimes, a frozen Mac can be so stuck that it requires forcibly rebooting to get the computer to behave again.

Note this setting was actually contained in the System Preferences for a while in earlier versions of OS X, but newer versions of Mac OS X removed the option and instead simply default to having the feature on.

systemsetup Help Information
-------------------------------------
Usage: systemsetup -getdate
        Display current date.

Usage: systemsetup -setdate <mm:dd:yy>
        Set current date to <mm:dd:yy>.

Usage: systemsetup -gettime
        Display current time.

Usage: systemsetup -settime <hh:mm:ss>
        Set current time to <hh:mm:ss>.

Usage: systemsetup -gettimezone
        Display current time zone.

Usage: systemsetup -settimezone <timezone>
        Set current time zone to <timezone>. Use "-listtimezones" to list time zones.

Usage: systemsetup -listtimezones
        List time zones supported by this machine.

Usage: systemsetup -getusingnetworktime
        Display whether network time is on or off.

Usage: systemsetup -setusingnetworktime <on off>
        Set using network time to either <on> or <off>.

Usage: systemsetup -getnetworktimeserver
        Display network time server.

Usage: systemsetup -setnetworktimeserver <timeserver>
        Set network time server to <timeserver>.

Usage: systemsetup -getsleep
        Display amount of idle time until computer, display and hard disk sleep.

Usage: systemsetup -setsleep <minutes>
        Set amount of idle time until computer, display and hard disk sleep to <minutes>.
        Specify "Never" or "Off" for never.

Usage: systemsetup -getcomputersleep
        Display amount of idle time until computer sleeps.

Usage: systemsetup -setcomputersleep <minutes>
        Set amount of idle time until compputer sleeps to <minutes>.
        Specify "Never" or "Off" for never.

Usage: systemsetup -getdisplaysleep
        Display amount of idle time until display sleeps.

Usage: systemsetup -setdisplaysleep <minutes>
        Set amount of idle time until display sleeps to <minutes>.
        Specify "Never" or "Off" for never.

Usage: systemsetup -getharddisksleep
        Display amount of idle time until hard disk sleeps.

Usage: systemsetup -setharddisksleep <minutes>
        Set amount of idle time until hard disk sleeps to <minutes>.
        Specify "Never" or "Off" for never.

Usage: systemsetup -getwakeonmodem
        Display whether wake on modem is on or off.

Usage: systemsetup -setwakeonmodem <on off>
        Set wake on modem to either <on> or <off>.

Usage: systemsetup -getwakeonnetworkaccess
        Display whether wake on network access is on or off.

Usage: systemsetup -setwakeonnetworkaccess <on off>
        Set wake on network access to either <on> or <off>.

Usage: systemsetup -getrestartpowerfailure
        Display whether restart on power failure is on or off.

Usage: systemsetup -setrestartpowerfailure <on off>
        Set restart on power failure to either <on> or <off>.

Usage: systemsetup -getrestartfreeze
        Display whether restart on freeze is on or off.

Usage: systemsetup -setrestartfreeze <on off>
        Set restart on freeze to either <on> or <off>.

Usage: systemsetup -getallowpowerbuttontosleepcomputer
        Display whether the power button is able to sleep the computer.

Usage: systemsetup -setallowpowerbuttontosleepcomputer <on off>
        Enable or disable whether the power button can sleep the computer.

Usage: systemsetup -getremotelogin
        Display whether remote login is on or off.

Usage: systemsetup -setremotelogin <on off>
        Set remote login to either <on> or <off>. Use "systemsetup -f -setremotelogin off" to suppress prompting when turning remote login off. Requires Full Disk Access privileges.

Usage: systemsetup -getremoteappleevents
        Display whether remote apple events are on or off.

Usage: systemsetup -setremoteappleevents <on off>
        Set remote apple events to either <on> or <off>. Requires Full Disk Access privileges.

Usage: systemsetup -getcomputername
        Display computer name.

Usage: systemsetup -setcomputername <computername>
        Set computer name to <computername>.

Usage: systemsetup -getlocalsubnetname
        Display local subnet name.

Usage: systemsetup -setlocalsubnetname <name>
        Set local subnet name to <name>.

Usage: systemsetup -getstartupdisk
        Display current startup disk.

Usage: systemsetup -setstartupdisk <disk>
        Set current startup disk to <disk>.

Usage: systemsetup -liststartupdisks
        List startup disks on this machine.

Usage: systemsetup -getwaitforstartupafterpowerfailure
        Get the number of seconds after which the computer will start up after a power failure.

Usage: systemsetup -setwaitforstartupafterpowerfailure <seconds>
        Set the number of seconds after which the computer will start up after a power failure. The <seconds> value must be a multiple of 30 seconds.

Usage: systemsetup -getdisablekeyboardwhenenclosurelockisengaged
        Get whether or not the keyboard should be disabled when the X Serve enclosure lock is engaged.

Usage: systemsetup -setdisablekeyboardwhenenclosurelockisengaged <yes no>
        Set whether or not the keyboard should be disabled when the X Serve enclosure lock is engaged.

Usage: systemsetup -version
        Display version of systemsetup tool.

Usage: systemsetup -help
        Display help.

Usage: systemsetup -printCommands
        Display commands.

Mac 的启动组合键

Mac 的啟動組合鍵

了解可通過在啟動時按住一個或多個按鍵來訪問的Mac 功能和工具。 
要使用這些組合鍵中的任何一個,請在按下電源按鈕以開啟Mac  後或在Mac開始重新啟動後,立即按住相應按鍵。請一直按住,直至電腦出現對應的行為。


你可以在Mac開機時,按住如下的組合鍵,去進入其功能設定:
  1. 按住〈C〉,從CD 或DVD 光碟機啟動,如:Mac OS X 安裝光碟。
  2. 按住〈D〉,如果插入安裝DVD 1,則啟動為Apple Hardware Test (AHT)。
  3. 按住〈Option〉+〈Command〉+〈P〉+〈R〉,直到聽到兩聲BB聲-->Reset NVRAM。
  4. 按住〈Option〉 ,開機後進入Startup Manager,你可以在這些選項中,選擇從一個你想的Mac OS X 項目去開機。注意:按住〈N〉 鍵,可顯示出第一個可啟動的網絡選項。你也可以選擇從UEFI磁碟作開機,去做一些內部設定。
  5. 按住〈Eject〉or〈F12〉 ,或者按住鼠標鍵(/觸控板),退出所有可移動的媒體,如光碟,USB。
  6. 按住〈N〉,試著從相容的網絡伺服器(NetBoot)去作開機的動作。
  7. 按住〈T〉,開機後成為FireWire 目標(Taget)的磁碟模式。
  8. 按住〈Shift〉,開機後成為安全模式,並且暫時關閉登錄選項。
  9. 按住〈Command〉+〈V〉,開機後成為Verbose 模式。
  10. 按住〈Command〉+〈S〉,開機後成為單一使用者模式。
  11. 按住〈Option〉+〈N〉,使用系統預設執的開機鏡像,從NetBoot伺服器開機。
若要從「macOS 復原」啟動,請將 Mac 開機,然後立即在鍵盤上按住下列其中一套組合鍵。在您看到 Apple 標誌、旋轉的地球或其他啟動畫面時,放開按鍵。

Command(⌘)-R

重新安裝 Mac 上所安裝的最新版 macOS(建議做法)。

Option-⌘-R

升級到與 Mac 相容的最新版 macOS。

Shift-Option-⌘-R

重新安裝 Mac 隨附的 macOS,或仍提供使用的最接近版本。