https://dev.clsung.tw/2025/01/%E7%94%A8-docker-compose-%E9%83%A8%E7%BD%B2-n8n/
啟動於http
docker run -d -p 5678:5678 -e N8N_SECURE_COOKIE=false n8nio/n8n
運用 google 的豐富資源,建立Richard`s 防忘記 Blog
https://dev.clsung.tw/2025/01/%E7%94%A8-docker-compose-%E9%83%A8%E7%BD%B2-n8n/
啟動於http
docker run -d -p 5678:5678 -e N8N_SECURE_COOKIE=false n8nio/n8n
在 Visual Studio 2017 裡面,有個好用的「分析器」功能,可以幫助開發人員寫好程式。他的作法是在背景執行一連串的程式碼分析,透過一組規則集 (RuleSet) 對專案中的程式碼進行剖析與檢查,如果有發現任何問題,就會在「錯誤清單」中呈現資訊、警告或錯誤,並且提供部分規則的自動修復功能。不過,在 Visual Studio 2017 對 .NET Core 專案的支援度並沒有太多文件著墨,我花了好多時間才研究出背後的差異之處。我打算透過本篇文章分享如何在 Visual Studio 2017 啟用與設定 .NET Core 專案的程式碼分析器功能。
基本上,在 Microsoft Docs 上關於 Visual Studio 2017 分析器的文件,所有的「操作步驟」大多都只適用於 .NET Framework 專案類型。到了 .NET Core 之後,雖然分析器的觀念都完全一樣,但是分析器的設定方式已經有點不一樣,這點真的困擾我一些時間。
以下我列出幾個重要的文件入口頁,先建立一些基本觀念再開始使用還是比較好:
早在十多年前,最知名的 FxCop 套件,就是用來分析 .NET Framework 專案原始碼,自動檢測潛在的程式碼問題。爾後被整併到 Visual Studio 之中,變成內建的程式分析器,雖然 FxCop 這個名詞變得少見,但內部還是一直使用這個名字。
直到 .NET Compiler Platform ("Roslyn") 出現之後,這一切都改變了。因為 Roslyn 將 NET 程式語言的編譯器全部開放原始碼,而且公開許多 C#/VB 程式碼剖析的 APIs,所以 Visual Studio 也開始進一步改用 Roslyn 改寫所有分析器。
簡單來說:目前 Visual Studio 2017 的分析器已經全數改用 Roslyn 進行程式碼分析。
在 Visual Studio 2017 建立任何一個 .NET Framework 專案範本,預設就會啟用內建的分析器。預設選取的規則集為 適用於 Managed 程式碼的 Managed 建議規則規則集 (Managed Recommended Rules rule set for managed code),這些規則的重點在於程式碼中最關鍵的問題,包括潛在的安全性漏洞、應用程式損毀,以及其他重要的邏輯和設計錯誤。
這份 適用於 Managed 程式碼的 Managed 建議規則規則集 文件的翻譯,在 Visual Studio 2017 中操作介面翻譯為 Microsoft 受控建議規則,有一點不太一樣。你可以從「專案屬性」的「程式碼分析」頁籤中看見。規則集檔案的路徑為 C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Team Tools\Static Analysis Tools\Rule Sets\MinimumRecommendedRules.ruleset。
這些規則集都是可以調整的,在 Visual Studio 2017 中完整的規則集文件,可以參考 程式碼分析規則集參考 文件。
在 Visual Studio 2017 的 .NET Framework 專案中開啟規則集,有兩種方法:
請注意:在 .NET Core 專案中,從 VS2017 的方案總管中,會完全找不到可以開啟程式碼分析器規則集的功能,從專案屬性中也會找不到程式碼分析頁籤,這點是有點不便!
最後提醒:透過 程式碼分析規則編輯器 對規則集檔案所做的修改,在 .NET Core 的專案中,完全無法產生效果!
我之前就是一直被 .NET Framework 專案的分析器設定步驟卡住,怎樣設定都無效,甚至設定到有點怒氣 XD
在 Visual Studio 2017 中對 .NET Core 專案設定分析器的完整設定步驟如下:
fxcopanalyzers
關鍵字,並安裝 Microsoft.CodeAnalysis.FxCopAnalyzers 套件。或直接透過套件管理器主控台輸入以下命令:(2018/09/24: 請記得安裝最新 Beta 版本。)
Install-Package Microsoft.CodeAnalysis.FxCopAnalyzers -IncludePrerelease
安裝好必要的分析器套件後,接下來就簡單測試一下。
你先隨便建立一個類別檔,並輸入以下內容,然後 [建置] 專案:
using System;
using System.IO;
...
...
public class NoDisposeMethod
{
FileStream newFile;
public NoDisposeMethod()
{
newFile = new FileStream(@"c:\temp.txt", FileMode.Open);
}
}
上述程式碼會引發 CA1001:具有可處置欄位的類型應該是可處置的 警告,你可以從 錯誤清單 中發現這些訊息。
Visual Studio 2017 預設只會分析目前開啟過的檔案,如果要預設分析方案中所有專案的所有程式碼,可以參考以下設定:
在 .NET Framework 可以透過建立 *.ruleset
檔案,你可以透過 [新增項目] 精靈,搜尋 [程式碼分析規則集] 項目範本,即可建立一個自訂規則集。在 Visual Studio 2017 中有個 程式碼分析規則編輯器 可用,不過這套編輯器完全不適用於 .NET Core 專案,千萬不要透過這套來編輯規則集內容。
在 .NET Core 專案中,調整規則集的方式,已經整合進 方案總管,你只要從 [專案] / [相依性] / [分析器] 去挑選適合的規則,直接按滑鼠右鍵,就可以切換該條規則的嚴重性。
只要你第一次切換任何一條規則的嚴重性設定,該專案就會自動建立規則集設定檔(*.ruleset
),並且全自動設定相容於 .NET Framework 的規則集。意思也就是說,只要你的方案中有 .NET Core 專案的存在,你就應該用 .NET Core 的規則集設定方法,而這些自動產生的規則集設定檔,也同時可以套用到 .NET Framework 專案中!
主控台應用程式 (.NET Core) & 類別庫 (.NET Core)
這兩個專案範本預設沒有內建任何分析器 (Analyzer)。
如果想要安裝額外的分析器,以下介紹的每個分析器套件,只要用 NuGet 安裝好就能直接使用。
只有在 主控台應用程式 (.NET Core) 與 類別庫 (.NET Core) 專案範本中,才看的見 程式碼分析規則集 (Code Analysis Rule Set) 這個「項目範本」(Item Template)。如果你在 ASP.NET Core Web 應用程式的專案中新增項目時,就會搜尋不到這個項目範本,要特別注意!
ASP.NET Core Web 應用程式
要使用 Microsoft.CodeAnalysis.FxCopAnalyzers 可以直接透過 NuGet 安裝 Microsoft.CodeAnalysis.FxCopAnalyzers 即可。
安裝過程除了會安裝 Microsoft.CodeAnalysis.FxCopAnalyzers 之外,也會連同安裝以下 4 個分析器。
安裝之後,會有以下分析器:
相關連結
資料來源:https://blog.miniasp.com/post/2018/09/24/Enabling-Code-Analysis-in-VS2017-for-NET-Core
延伸資料
[iThome第8屆鐵人賽 19]靜態程式碼分析之Assembly品質分析 - Code Analysis(以前的FxCop)
https://blog.alantsai.net/posts/2017/01/devopsseries-codeanalysis
程式算法本身的複雜度
CPU的速度和設計架構
CPU的位元帶寬
自己的程式的寫法
#define OLED_SDA D2 // D2
#define OLED_SCL D1 // D1
#define OLED_ADDRESS 0x3c // SSD1306 I2C 地址
// I2C 延遲,控制速度
#define I2C_DELAY 50 // 試著增加延遲
void i2c_start() {
pinMode(OLED_SDA, OUTPUT);
pinMode(OLED_SCL, OUTPUT);
digitalWrite(OLED_SDA, HIGH);
digitalWrite(OLED_SCL, HIGH);
delayMicroseconds(I2C_DELAY);
digitalWrite(OLED_SDA, LOW);
delayMicroseconds(I2C_DELAY);
digitalWrite(OLED_SCL, LOW);
}
void i2c_stop() {
pinMode(OLED_SDA, OUTPUT);
pinMode(OLED_SCL, OUTPUT);
digitalWrite(OLED_SDA, LOW);
digitalWrite(OLED_SCL, HIGH);
delayMicroseconds(I2C_DELAY);
digitalWrite(OLED_SDA, HIGH);
}
bool i2c_write_byte(uint8_t byte) {
pinMode(OLED_SDA, OUTPUT);
for (int i = 0; i < 8; i++) {
digitalWrite(OLED_SCL, LOW);
if (byte & 0x80) {
digitalWrite(OLED_SDA, HIGH);
} else {
digitalWrite(OLED_SDA, LOW);
}
byte <<= 1;
delayMicroseconds(I2C_DELAY);
digitalWrite(OLED_SCL, HIGH);
delayMicroseconds(I2C_DELAY);
}
digitalWrite(OLED_SCL, LOW);
pinMode(OLED_SDA, INPUT); // 切換到輸入檢查 ACK
delayMicroseconds(I2C_DELAY);
digitalWrite(OLED_SCL, HIGH);
bool ack = !digitalRead(OLED_SDA); // ACK 應該為低
delayMicroseconds(I2C_DELAY);
digitalWrite(OLED_SCL, LOW);
return ack; // 返回 ACK 檢查結果
}
void oled_command(uint8_t command) {
i2c_start();
uint8_t address = OLED_ADDRESS << 1;
Serial.print("Sending Address: ");
Serial.println(address, HEX);
if (!i2c_write_byte(address)) {
Serial.println("Address not acknowledged");
}
if (!i2c_write_byte(0x00)) {
Serial.println("Control byte not acknowledged");
}
if (!i2c_write_byte(command)) {
Serial.println("Command not acknowledged");
}
i2c_stop();
}
void oled_init() {
oled_command(0xAE); // 關閉顯示
oled_command(0xA8); // 設置多路復用比率
oled_command(0x3F); // 1/64
oled_command(0xD3); // 設置顯示偏移
oled_command(0x00); // 無偏移
oled_command(0x40); // 設置起始行位置
oled_command(0xA1); // 設置重映射
oled_command(0xC8); // 掃描方向
oled_command(0xDA); // 設置 COM 硬體配置
oled_command(0x12); // 代碼段
oled_command(0x81); // 設置對比度
oled_command(0x7F);
oled_command(0xA4); // 關閉整體顯示
oled_command(0xA6); // 設置普通顯示
oled_command(0xD5); // 設置顯示時鐘分頻比/振盪器頻率
oled_command(0x80);
oled_command(0x8D); // 啟用充電泵
oled_command(0x14);
oled_command(0xAF); // 打開顯示
}
void oled_clear() {
for (uint8_t page = 0; page < 8; page++) {
oled_command(0xB0 + page); // 設置頁地址
oled_command(0x00); // 設置低列地址
oled_command(0x10); // 設置高列地址
i2c_start();
i2c_write_byte(OLED_ADDRESS << 1); // 發送地址
i2c_write_byte(0x40); // 控制位元 (0x40 表示後面是數據)
for (uint8_t col = 0; col < 128; col++) {
i2c_write_byte(0x00); // 清空顯示
}
i2c_stop();
}
}
// 定義 5x7 點陣字體
const uint8_t font5x7[][6] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // sp
{0x00, 0x00, 0x00, 0x2f, 0x00, 0x00}, // !
{0x00, 0x00, 0x07, 0x00, 0x07, 0x00}, // "
{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14}, // #
{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12}, // $
{0x00, 0x62, 0x64, 0x08, 0x13, 0x23}, // %
{0x00, 0x36, 0x49, 0x55, 0x22, 0x50}, // &
{0x00, 0x00, 0x05, 0x03, 0x00, 0x00}, // '
{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00}, // (
{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00}, // )
{0x00, 0x14, 0x08, 0x3E, 0x08, 0x14}, // *
{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08}, // +
{0x00, 0x00, 0x00, 0xA0, 0x60, 0x00}, // ,
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08}, // -
{0x00, 0x00, 0x60, 0x60, 0x00, 0x00}, // .
{0x00, 0x20, 0x10, 0x08, 0x04, 0x02}, // /
{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0
{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00}, // 1
{0x00, 0x42, 0x61, 0x51, 0x49, 0x46}, // 2
{0x00, 0x21, 0x41, 0x45, 0x4B, 0x31}, // 3
{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10}, // 4
{0x00, 0x27, 0x45, 0x45, 0x45, 0x39}, // 5
{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6
{0x00, 0x01, 0x71, 0x09, 0x05, 0x03}, // 7
{0x00, 0x36, 0x49, 0x49, 0x49, 0x36}, // 8
{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E}, // 9
{0x00, 0x00, 0x36, 0x36, 0x00, 0x00}, // :
{0x00, 0x00, 0x56, 0x36, 0x00, 0x00}, // ;
{0x00, 0x08, 0x14, 0x22, 0x41, 0x00}, // <
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14}, // =
{0x00, 0x00, 0x41, 0x22, 0x14, 0x08}, // >
{0x00, 0x02, 0x01, 0x51, 0x09, 0x06}, // ?
{0x00, 0x32, 0x49, 0x59, 0x51, 0x3E}, // @
{0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C}, // A
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36}, // B
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22}, // C
{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C}, // D
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41}, // E
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01}, // F
{0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A}, // G
{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F}, // H
{0x00, 0x00, 0x41, 0x7F, 0x41, 0x00}, // I
{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01}, // J
{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41}, // K
{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40}, // L
{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F}, // M
{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F}, // N
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E}, // O
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06}, // P
{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q
{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46}, // R
{0x00, 0x46, 0x49, 0x49, 0x49, 0x31}, // S
{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01}, // T
{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F}, // U
{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F}, // V
{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F}, // W
{0x00, 0x63, 0x14, 0x08, 0x14, 0x63}, // X
{0x00, 0x07, 0x08, 0x70, 0x08, 0x07}, // Y
{0x00, 0x61, 0x51, 0x49, 0x45, 0x43}, // Z
{0x00, 0x00, 0x7F, 0x41, 0x41, 0x00}, // [
{0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55}, // backslash
{0x00, 0x00, 0x41, 0x41, 0x7F, 0x00}, // ]
{0x00, 0x04, 0x02, 0x01, 0x02, 0x04}, // ^
{0x00, 0x40, 0x40, 0x40, 0x40, 0x40}, // _
{0x00, 0x00, 0x01, 0x02, 0x04, 0x00}, // '
{0x00, 0x20, 0x54, 0x54, 0x54, 0x78}, // a
{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38}, // b
{0x00, 0x38, 0x44, 0x44, 0x44, 0x20}, // c
{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F}, // d
{0x00, 0x38, 0x54, 0x54, 0x54, 0x18}, // e
{0x00, 0x08, 0x7E, 0x09, 0x01, 0x02}, // f
{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C}, // g
{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78}, // h
{0x00, 0x00, 0x44, 0x7D, 0x40, 0x00}, // i
{0x00, 0x40, 0x80, 0x84, 0x7D, 0x00}, // j
{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00}, // k
{0x00, 0x00, 0x41, 0x7F, 0x40, 0x00}, // l
{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78}, // m
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x78}, // n
{0x00, 0x38, 0x44, 0x44, 0x44, 0x38}, // o
{0x00, 0xFC, 0x24, 0x24, 0x24, 0x18}, // p
{0x00, 0x18, 0x24, 0x24, 0x18, 0xFC}, // q
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x08}, // r
{0x00, 0x48, 0x54, 0x54, 0x54, 0x20}, // s
{0x00, 0x04, 0x3F, 0x44, 0x40, 0x20}, // t
{0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C}, // u
{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C}, // v
{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C}, // w
{0x00, 0x44, 0x28, 0x10, 0x28, 0x44}, // x
{0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C}, // y
{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44}, // z
{0x7E, 0x10, 0x10, 0x10, 0x7E, 0x00}, // 'H'
{0x7E, 0x4A, 0x4A, 0x4A, 0x42, 0x00}, // 'E'
{0x7E, 0x40, 0x40, 0x40, 0x40, 0x00}, // 'L'
{0x3C, 0x42, 0x42, 0x42, 0x3C, 0x00}, // 'O'
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // '#'
};
const char ssd1306oled_font[][6] PROGMEM = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // sp
{0x00, 0x00, 0x00, 0x2f, 0x00, 0x00}, // !
{0x00, 0x00, 0x07, 0x00, 0x07, 0x00}, // "
{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14}, // #
{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12}, // $
{0x00, 0x62, 0x64, 0x08, 0x13, 0x23}, // %
{0x00, 0x36, 0x49, 0x55, 0x22, 0x50}, // &
{0x00, 0x00, 0x05, 0x03, 0x00, 0x00}, // '
{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00}, // (
{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00}, // )
{0x00, 0x14, 0x08, 0x3E, 0x08, 0x14}, // *
{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08}, // +
{0x00, 0x00, 0x00, 0xA0, 0x60, 0x00}, // ,
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08}, // -
{0x00, 0x00, 0x60, 0x60, 0x00, 0x00}, // .
{0x00, 0x20, 0x10, 0x08, 0x04, 0x02}, // /
{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0
{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00}, // 1
{0x00, 0x42, 0x61, 0x51, 0x49, 0x46}, // 2
{0x00, 0x21, 0x41, 0x45, 0x4B, 0x31}, // 3
{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10}, // 4
{0x00, 0x27, 0x45, 0x45, 0x45, 0x39}, // 5
{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6
{0x00, 0x01, 0x71, 0x09, 0x05, 0x03}, // 7
{0x00, 0x36, 0x49, 0x49, 0x49, 0x36}, // 8
{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E}, // 9
{0x00, 0x00, 0x36, 0x36, 0x00, 0x00}, // :
{0x00, 0x00, 0x56, 0x36, 0x00, 0x00}, // ;
{0x00, 0x08, 0x14, 0x22, 0x41, 0x00}, // <
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14}, // =
{0x00, 0x00, 0x41, 0x22, 0x14, 0x08}, // >
{0x00, 0x02, 0x01, 0x51, 0x09, 0x06}, // ?
{0x00, 0x32, 0x49, 0x59, 0x51, 0x3E}, // @
{0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C}, // A
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36}, // B
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22}, // C
{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C}, // D
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41}, // E
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01}, // F
{0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A}, // G
{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F}, // H
{0x00, 0x00, 0x41, 0x7F, 0x41, 0x00}, // I
{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01}, // J
{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41}, // K
{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40}, // L
{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F}, // M
{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F}, // N
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E}, // O
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06}, // P
{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q
{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46}, // R
{0x00, 0x46, 0x49, 0x49, 0x49, 0x31}, // S
{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01}, // T
{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F}, // U
{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F}, // V
{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F}, // W
{0x00, 0x63, 0x14, 0x08, 0x14, 0x63}, // X
{0x00, 0x07, 0x08, 0x70, 0x08, 0x07}, // Y
{0x00, 0x61, 0x51, 0x49, 0x45, 0x43}, // Z
{0x00, 0x00, 0x7F, 0x41, 0x41, 0x00}, // [
{0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55}, // backslash
{0x00, 0x00, 0x41, 0x41, 0x7F, 0x00}, // ]
{0x00, 0x04, 0x02, 0x01, 0x02, 0x04}, // ^
{0x00, 0x40, 0x40, 0x40, 0x40, 0x40}, // _
{0x00, 0x00, 0x01, 0x02, 0x04, 0x00}, // '
{0x00, 0x20, 0x54, 0x54, 0x54, 0x78}, // a
{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38}, // b
{0x00, 0x38, 0x44, 0x44, 0x44, 0x20}, // c
{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F}, // d
{0x00, 0x38, 0x54, 0x54, 0x54, 0x18}, // e
{0x00, 0x08, 0x7E, 0x09, 0x01, 0x02}, // f
{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C}, // g
{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78}, // h
{0x00, 0x00, 0x44, 0x7D, 0x40, 0x00}, // i
{0x00, 0x40, 0x80, 0x84, 0x7D, 0x00}, // j
{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00}, // k
{0x00, 0x00, 0x41, 0x7F, 0x40, 0x00}, // l
{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78}, // m
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x78}, // n
{0x00, 0x38, 0x44, 0x44, 0x44, 0x38}, // o
{0x00, 0xFC, 0x24, 0x24, 0x24, 0x18}, // p
{0x00, 0x18, 0x24, 0x24, 0x18, 0xFC}, // q
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x08}, // r
{0x00, 0x48, 0x54, 0x54, 0x54, 0x20}, // s
{0x00, 0x04, 0x3F, 0x44, 0x40, 0x20}, // t
{0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C}, // u
{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C}, // v
{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C}, // w
{0x00, 0x44, 0x28, 0x10, 0x28, 0x44}, // x
{0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C}, // y
{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44}, // z
{0x00, 0x00, 0x08, 0x77, 0x41, 0x00}, // {
{0x00, 0x00, 0x00, 0x63, 0x00, 0x00}, // ¦
{0x00, 0x00, 0x41, 0x77, 0x08, 0x00}, // }
{0x00, 0x08, 0x04, 0x08, 0x08, 0x04}, // ~
/* end of normal char-set */
/* put your own signs/chars here, edit special_char too */
/* be sure that your first special char stand here */
{0x00, 0x3A, 0x40, 0x40, 0x20, 0x7A}, // ü, !!! Important: this must be special_char[0] !!!
{0x00, 0x3D, 0x40, 0x40, 0x40, 0x3D}, // Ü
{0x00, 0x21, 0x54, 0x54, 0x54, 0x79}, // ä
{0x00, 0x7D, 0x12, 0x11, 0x12, 0x7D}, // Ä
{0x00, 0x39, 0x44, 0x44, 0x44, 0x39}, // ö
{0x00, 0x3D, 0x42, 0x42, 0x42, 0x3D}, // Ö
{0x00, 0x02, 0x05, 0x02, 0x00, 0x00}, // °
{0x00, 0x7E, 0x01, 0x49, 0x55, 0x73}, // ß
{0x00, 0x7C, 0x10, 0x10, 0x08, 0x1C}, // µ
{0x00, 0x30, 0x48, 0x20, 0x48, 0x30}, // ω
{0x00, 0x5C, 0x62, 0x02, 0x62, 0x5C} // Ω
};
// 顯示字符的功能
void oled_display_char(uint8_t c) {
i2c_start();
i2c_write_byte(OLED_ADDRESS << 1); // 發送地址
i2c_write_byte(0x40); // 控制位元 (0x40 表示後面是數據)
// 發送 5x7 字符數據
c = c - ' ';
for (uint8_t i = 0; i < 6; i++) {
i2c_write_byte(font5x7[c][i]);
}
// 6th byte is space between characters
//i2c_write_byte(0x00);
i2c_stop();
}
// 顯示字符串
void oled_display_string(uint8_t x, uint8_t y, const char* str) {
oled_command(0xB0 + y); // 設置頁地址
oled_command(0x00); // 設置低列地址
oled_command(0x10 + x); // 設置高列地址
while (*str) {
oled_display_char(*str);
/*
if (*str == 'H') oled_display_char(0);
if (*str == 'E') oled_display_char(1);
if (*str == 'L') oled_display_char(2);
if (*str == 'O') oled_display_char(3);
if (*str == '#') oled_display_char(4);
*/
str++;
}
}
void setup() {
Serial.begin(9600);
delay(100);
//setup2();
pinMode(OLED_SDA, OUTPUT);
pinMode(OLED_SCL, OUTPUT);
// 初始化 OLED
oled_init();
// 測試顯示,打開所有像素
//oled_command(0xA5); // 這個指令讓所有像素點亮
// 清空顯示屏
oled_clear();
// 顯示 "HELLO"
oled_display_string(0, 0, "12345678901234567890");
oled_display_string(0, 1, "ABCDEFGHIJKLMNOPQRST");
oled_display_string(0, 2, "abcdefghijklmnopqrst");
oled_display_string(0, 3, "!@#$%^&*()_+-=,./;'?");
oled_display_string(0, 7, "H####");
}
void loop() {
// 空的 loop
}
/*
#include <Wire.h>
void setup2() {
Wire.begin();
Serial.begin(9600);
Serial.println("\nI2C Scanner");
for (uint8_t address = 1; address < 127; address++) {
Wire.beginTransmission(address);
if (Wire.endTransmission() == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16) {
Serial.print("0");
}
Serial.println(address, HEX);
}
}
Serial.println("Done");
}
*/
未修補的漏洞是網路犯罪分子最容易攻擊的目標之一。企業中很多的資料安全事件往往由於已知的漏洞造成的,儘管相關的安全補丁已經發布,但許多企業由於種種原因並不能及時發現並修補這些漏洞。
當組織想要開展全面且持續的漏洞掃描工作時,通常需要得到廣泛的安全社區支持。在此過程中,安全人員可以藉助一些的流行開源漏洞掃描工具。由於它們具有開放源程式碼的特性,使用者可以自由地查看、修改和定製這些工具,以滿足自身的安全需求。此外,這些工具會經常更新和改進以適應不斷變化的漏洞威脅。本文收集了6款目前較熱門的開源漏洞掃描工具(詳見下表),並從功能性、兼容性和可擴展性等方面對其應用特點進行了分析。
1、Nmap
Nmap是一款非常流行的自動化安全測試工具。它可以在各種主流作業系統上運行,並快速掃描大型網路。它通常會檢測以下資訊:網路上有哪些主機可用,主機在運行什麼服務,主機在運行哪些作業系統版本,使用哪種類型的資料包過濾器和防火牆,以及發動攻擊之前需要的其他有用情報。此外,Nmap的說明文件也很全面,還有針對命令列和GUI(圖形化操作界面)版本的眾多教程,很容易上手。
主要特點
ㆍ快速查詢開放埠,基於可用的 TCP 和 UDP 服務分析協議、應用程序和作業系統。
ㆍ擁有龐大的活躍使用者群,也被大多數網路和網路安全認證計劃所接受。
ㆍ對使用者友好,使用命令列控制元件自動執行漏洞掃描或將結果匯出到票證系統或安全工具中。
ㆍ包含一個不斷增長的檢測腳本庫,可用於增強網路發現和漏洞評估的功能。
ㆍ可基於協議請求的埠響應進行掃描,適用於所有具有開放埠的計算機、物聯網設備、網站、雲系統和網路設備。
不足
ㆍ沒有正式的客戶支持選項
ㆍ使用時需要一定的經驗或程式設計能力
ㆍ並非所有選項在 GUI 版本中都可用
2、OpenVAS
OpenVAS是一個較全面的開源滲透測試軟體。在世界各地的滲透測試專家的幫助下,它得到了不斷的支持和更新,從而使其保持最新狀態。OpenVAS的其他特性還包括提供未經身份驗證的測試、目標掃描和web漏洞掃描。需要說明的是,OpenVAS工具的漏洞掃描能力最初是從Nessus產品派生而來,後者現在是Tenable公司的非開源商業化產品。
主要特點
ㆍ幾乎每天都會更新威脅資訊源,並定期提供產品更新和功能更新。
ㆍ免費版本的功能就非常全面,並在企業版本中提供更多功能和特性,同時提供客戶支持。
ㆍ能夠對終端、伺服器和雲等多種系統進行常見漏洞和曝光(CVE)的掃描。
ㆍ產品得到主流網路安全社區的支持,能夠在許多不同的認證課程中教授。
ㆍ可以為每個漏洞提供額外的上下文資訊,用於漏洞修復或攻擊路徑解釋。
不足
ㆍ對於初學者來說專業門檻較高
ㆍ在同時進行多個掃描任務時,可能會導致程序崩潰
ㆍ一些高級掃描功能需要使用付費版本
3、ZAP
Zed Attack Proxy (ZAP)是一款使用者友好的滲透測試工具,能找出網路應用中的漏洞。它不僅提供自動化掃描器,也為想要手動查找漏洞的使用者提供了一套工具。ZAP通常預裝在Kali Linux上,它能夠將自身置於測試人員的瀏覽器和Web應用程序之間,攔截請求以充當”代理”。通過修改內容、轉發資料包和模擬其他使用者行為,ZAP也可以對應用程序進行漏洞掃描測試。
主要特點
ㆍ可執行常見的動態應用程序安全測試 (DAST),特別是針對跨站點腳本 (XSS) 漏洞,還能夠執行一些新型的測試工作,例如模糊測試;
ㆍ可提供 API 和 docker 集成以實現快速部署,並與 DevSecOp 工具集成,實現對開發團隊的自動化工單管理;
ㆍ通過Crash Override開源獎學金的支持,ZAP擁有多名全職開發人員,不再與OWASP有關聯;
ㆍ經常被滲透測試人員使用,可以很好地了解駭客可能發現的漏洞。
不足
ㆍ某些掃描功能需要額外的外掛
ㆍ需要一些專業知識才能使用
ㆍ相比其他工具,誤報率較高
4、OSV-Scanner
OSV-Scanner是一款由Google公司開發的開源漏洞掃描工具,提供專門的軟體組成分析(SCA),可用於掃描靜態軟體,以確保開源軟體的程式設計程式碼安全漏洞,並保護開源軟體清單(SBOM)。在掃描項目時,OSV-Scanner 首先通過分析清單、軟體材料清單(SBOM)和程式碼提交哈希值來確定正在使用的所有依賴項。這些資訊用於查詢 OSV 資料庫,並報告與項目相關的漏洞。漏洞通過表格的形式或基於 JSON 的 OSV 格式(可選)進行報告。
主要特點
ㆍ能夠定期擴展支持的程式語言列表,包括C/C++、Dart、Elixir、Go、Java、JavaScript、PHP、Python、R、Ruby和Rust。
ㆍ可以從大量資訊源中獲取漏洞,包括Debian、Linux、Maven、npm、NuGet、OSS-Fuzz、Packagist、PyPl和RubyGems。
ㆍ允許API、可腳本化和與GitHub集成的調用,以實現漏洞掃描自動化。
ㆍ使用JSON儲存有關受影響版本的資訊,以便與開發人員工具包進行集成。
ㆍ檢查目錄、軟體清單(SBOM)、鎖定檔案、基於Debian的Docker映象或在Docker容器中運行的軟體。
不足
ㆍ只檢查開源庫中有的漏洞
ㆍ產品較新,尚未被納入到主流的認證教育中
5、CloudSploit
CloudSploit是一款開源的雲基礎設施掃描引擎,目前被Aqua公司收購併繼續對其進行維護,以使使用者能夠下載、修改並享受這個專業工具的好處。CloudSploit可以根據使用者需求進行掃描,也可以配置為持續運行,並向安全和DevOps團隊發送漏洞警報。該工具不僅檢查已知的雲和容器部署漏洞,還能夠檢查常見的配置錯誤問題。
主要特點
ㆍ可持續掃描AWS、Azure、Google Cloud、Oracle Cloud等環境,以便對雲基礎設施的更改進行警報。
ㆍ通過安全人員常用的工具(如Slack、Splunk、OpsGenie、Amazon SNS等)發送實時警報和結果。
ㆍ可從命令列、腳本或構建系統(Jenkins、CircleCL、AWS CodeBuild 等)調用 API。
ㆍ提供了廣泛的雲支持,包括針對主要公共雲平臺(阿里雲、AWS、Azure、Google Cloud 等)的外掛嚴重程度。
不足
ㆍ某些功能需要付費使用
ㆍ必須與其他安全工具一起使用
ㆍ專注於公有云基礎設施安全性
6、sqlmap
sqlmap是一款專注但功能強大的免費資料庫漏洞掃描工具。儘管其適用範圍有限,但在一些需要進行嚴格合規和安全測試的數字化業務場景中,資料庫漏洞測試往往是至關重要的組成部分。SQLmap能夠自動化查找與SQL隱碼攻擊相關的威脅和攻擊的過程。相比其他的web應用程序滲透測試工具,SQLmap具有較強大的測試引擎和多種注入攻擊識別能力,並支持多種資料庫伺服器,如MySQL、Microsoft Access、IBM DB2和SQLite。
主要特點
ㆍ可通過DBMS憑據、IP地址、埠和資料庫名稱直接連接到資料庫進行漏洞掃描測試。
ㆍ支持可調用的(程式碼或GitHub)集成,可執行任意命令,檢索標準輸出並生成報告。
ㆍ可掃描多種類型的SQL隱碼攻擊,包括:基於布爾的盲注、基於時間的盲注、基於錯誤的注入、基於UNION查詢的注入、堆疊查詢和帶外注入等。
ㆍ自動識別和使用密碼哈希進行具有許可訪問許可權的測試,還可以進行密碼破解。
ㆍ支持超過30個資料庫管理系統。
不足
ㆍ沒有圖形使用者界面,需要通過命令列
ㆍ只針對資料庫中的漏洞
ㆍ需要一定的資料庫專業知識才能有效使用
資料來源:https://vitomag.com/code/d0vr1
資料來源:https://aict.nkust.edu.tw/digitrans/?p=5858
You can manage remote desktop settings using the Ubuntu Settings application or the grdctl tool on the command line. However, you would better perform the first enabling using the GUI, because it is necessary to create keys for FreeRDP, and it is much easier in the GUI than in the command line.
Open Settings -> Sharing -> Remote Desktop.
And then enable Remote Desktop and Remote Control switches:
In the Authentication section, you can view or change your username and password:
After that, you can ensure that gnome-remote-desktop service is running using the following command:
systemctl status --user gnome-remote-desktop
And then, ensure that the service is waiting for connections on port 3389:
ss -tulpn | grep 3389
資料來源:https://losst.pro/en/how-to-enable-remote-desktop-in-ubuntu-22-04-23-10
Ubuntu 在20.X及22.X版本預設已把/etc/rc.local開機啟動服務關閉,小編今天要來介紹如何啟動該服務。
01、編輯rc-local服務檔案
指令語法:
sudo vi /lib/systemd/system/rc-local.service
在該文件最下方新增下列三行設定:
[Install] WantedBy=multi-user.target Alias=rc-local.service
02、設定開機啟動檔案
指令語法:
sudo vi /etc/rc.local
在該文件新增想要執行的指令:
#!/bin/sh -e /usr/bin/mount --bind /opt/api_7927 /var/www/html/api_7927
03、設定開機啟動檔案為可執行
指令語法:
sudo chmod u+x /etc/rc.local
04、設定開機啟動rc-local服務
指令語法:
sudo systemctl enable rc-local sudo systemctl start rc-local
資料來源: https://ailog.tw/lifelog/2023/11/03/ubuntu-rc-local/