2024 年 5 月

系統

使用 awk 擷取 Log 檔的特定欄位

想要從 Apache 的 log 檔擷取特定欄位。

下面是問 ChatGPT 的回答:

// 要使用 awk 指令從 Apache 日誌中提取第一欄(IP 地址)和第四欄(時間戳)的數據
// 可以使用以下命令
// '{print $1, $4}' 意思是印出第一欄和第四欄
$ awk '{print $1, $4}' log_file

// 不過,第四欄的時間戳會包含方括號,你可以用 awk 去除方括號,使輸出更乾淨
// gsub(/\[|\]/, "", $4) 是 awk 的一個函數調用,用來替換 $4 欄中的方括號 [ 和 ]
// 將其替換為空字符串 ""
$ awk '{gsub(/\[|\]/, "", $4); print $1, $4}' log_file

下面是我自己修改後的寫法:

// 欄位之間的 \t 是 tab 的意思
$ awk '{gsub(/\[|\]/, "", $4); gsub(/\"/, "", $7); print $1 "\t" $4 "\t" $7 "\t" $9 "\t" $10}' log_file
網頁

[JS] 日期

取得格式為 YYYY-MM-DD 的今天日期。

下面是問 ChatGPT 的結果:

const today = new Date();

const year = today.getFullYear();

// 月份從 0 開始,所以要加 1,並確保兩位數
const month = String(today.getMonth() + 1).padStart(2, '0');

// 確保日期為兩位數
const day = String(today.getDate()).padStart(2, '0');

const formattedDate = `${year}-${month}-${day}`;

// 2024-05-23
console.log(formattedDate);

在網路上還看到其他方式:

const today = new Date();

const year = today.getFullYear();
const month = ('0' + (today.getMonth() + 1)).slice(-2);
const date = ('0' + today.getDate()).slice(-2);

const hours = ('0' + today.getHours()).slice(-2);
const minutes = ('0' + today.getMinutes()).slice(-2);
const seconds = ('0' + today.getSeconds()).slice(-2);

// 2024-05-23 10:55:11
console.log(`${year}-${month}-${date} ${hours}:${minutes}:${seconds}`);

———

取得最近七天日期。

下面是問 ChatGPT 的結果:

const today = new Date();

for (let i = 0; i < 7; i++) {
  const tempDate = new Date();

  // 設定日期為今天減去 i 天
  tempDate.setDate(today.getDate() - i);

  const year = tempDate.getFullYear();

  // 月份從 0 開始,所以要加 1,並確保兩位數
  const month = String(tempDate.getMonth() + 1).padStart(2, '0');

  // 確保日期為兩位數
  const day = String(tempDate.getDate()).padStart(2, '0');

  const formattedDate = `${year}-${month}-${day}`;
  
  console.log(formattedDate);
}

在網路上看到的方式:

const today = new Date();

for (let i = 0; i < 7; i++) {
  const newDate = new Date(today.getTime() - i * 24 * 60 * 60 * 1000);
  
  const year = newDate.getFullYear();
  const month = String(newDate.getMonth() + 1).padStart(2, '0');
  const day = String(newDate.getDate()).padStart(2, '0');
  
  const formattedDate = `${year}-${month}-${day}`;
  
  console.log(formattedDate);
}


其他參考連結:

系統

監控網路連線狀態

同事有監控網路連線狀態並開關軟體的需求,請我做個小工具。

運作方式:每五秒會 ping 三個 DNS,三個 DNS 都沒回應就判斷網路有問題,會把斷線時間寫入檔案,並關掉指定軟體。三個 DNS 都有回應代表正常。網路有問題又回復連線的話,會等待三十秒再把指定軟體打開。

下面是 Node.js 的 code,有用到 ping 這個 package。

const { execSync, execFile } = require('child_process');
const fs = require('fs');
const ping = require('ping');

const hosts = ['168.95.1.1', '8.8.8.8', '1.1.1.1'];
const appName = 'app.exe';
const appPath = `C:\\Program Files (x86)\\App\\${appName}`;

let status;
let isClosed = false;
let intervalId;
let countdown = 30;

setInterval(() => {
  let onCount = 0;
  let offCount = 0;

  hosts.forEach((host) => {
    ping.sys.probe(host, (isAlive) => {
      if (isAlive) {
        onCount++;
        console.log(`${host} (on)`);

        // 連線正常
        if (onCount >= hosts.length) {
          console.log('--- Status: Online ---');

          // 連線回復
          if (status === 'OFFLINE') {
            status = '';
            console.log('Status: Network Back....');

            // 啟動 app
            launchApp();
          }
        }
      } else {
        offCount++;
        console.log(`${host} (off)`);

        // 連線有問題
        if (offCount >= hosts.length) {
          status = 'OFFLINE';
          console.log(`==== Status: ${status} [${getDateTime()}] ====`);

          // 寫入斷線時間
          logOffline();

          // 關閉 app
          if (!isClosed) {
            closeApp();
          }
        }
      }
    });
  });
}, 5000);

function closeApp() {
  isClosed = true;
  // console.log('closeApp()-isClosed:', isClosed);

  setTimeout(() => {
    console.log('Close App');
    execSync(`taskkill /f /im ${appName} /t`);
  }, 2000);
}

function launchApp() {
  isClosed = false;
  // console.log('launchApp()-isClosed:', isClosed);

  intervalId = setInterval(() => {
    console.log(`Countdown: ${countdown--}`);

    if (countdown === 0) {
      // console.log('clear-intervalId:', intervalId);
      clearInterval(intervalId);

      countdown = 30;

      console.log('Launch App');
      execFile(appPath);
    }
  }, 1000);

  // console.log('set-intervalId:', intervalId);
}

function getDateTime() {
  let today = new Date();

  let year = today.getFullYear();
  let month = ('0' + (today.getMonth() + 1)).slice(-2);
  let date = ('0' + today.getDate()).slice(-2);

  let hours = ('0' + today.getHours()).slice(-2);
  let minutes = ('0' + today.getMinutes()).slice(-2);
  let seconds = ('0' + today.getSeconds()).slice(-2);

  return `${year}-${month}-${date} ${hours}:${minutes}:${seconds}`;
}

function logOffline() {
  const data = `OFFLINE ${getDateTime()}\n`;

  fs.appendFile('offline_log.txt', data, 'utf8', (err) => {
    if (err) {
      console.log('Err:', err);
    }
  });
}


參考連結:

網頁

[Vue] Global State with Composables

在 Vue Composition API 下,想要有全域狀態,但又不用 Pinia,可以使用下面的方法:

// 檔名:useTest.js

import { ref, readonly } from 'vue';

// 有 import 這個檔案的 .vue 都可以使用這個 ref
const global = ref(0);

export function useTest() {
  // import 這個檔案的 .vue 檔,各自有這個 ref
  const count = ref(0);

  const countPlus = () => {
    count.value++;
  };

  const globalPlus = () => {
    global.value++;
  };

  return {
    // 設定全域 ref 唯讀,只能透過 return 的 function 修改
    global: readonly(global),
    globalPlus,
    count,
    countPlus
  };
}


參考連結:

返回頂端