---
# System prepended metadata

title: Linux LLC專題
tags: [apache, mariadb, 爬蟲, LinuxCCP, python, 專案一]

---

# Linux LLC專題
### 基礎專案1
1. [HTTP]使用 noip.com 服務，建立各組主網域位置(如 dv105.ddns.net)，透過主網域可看到各組網頁內容(PHP套件可架設之網站)
2. [DB]啟用 MariaDB 服務。
3. [FS]啟用 NFS&SAMBA 伺服器。

#### 第一題:
* 架設Apache與調整首頁
    1. 在Ubuntu安裝Apache、設置防火牆
    ```
    $ sudo apt update && sudo apt install apache2
    $ #防火牆先不要做 sudo apt install ufw 
    $ #防火牆先不要做sudo ufw allow OpenSSH
    $ #防火牆先不要做sudo ufw allow in "Apache Full"
    $ #防火牆先不要做sudo ufw enable
    $ #防火牆先不要做sudo ufw status #檢查當前的防火牆狀態
    $ sudo service apache2 status #若已啟動是綠色的Active
    ```
    2.在文件夾 /var/www/html 中找到這個 Apache 默認歡迎頁面
    ```
    $ sudo vi /var/www/html/index.html
    ```
    3. 替換index.html就可以換成自己想要的網頁
    4. 到noip註冊免費網域指向主機ip
![](https://hackmd.io/_uploads/SyMVHuvBh.jpg)

* 在同一台主機上用Virtual Host做兩個資料夾給兩個不同網域指向。
    1. 在 /var/www/ 目錄中為兩個網域建立兩個新目錄
    ```
    $ sudo mkdir -p /var/www/html/sundial.ddns.net/public_html
    $ sudo mkdir -p /var/www/html/mapleyu.ddns.net/public_html
    $ sudo chmod -R 755 /var/www
    ```
    2. 為兩個目錄新增兩個index.html
    ```
    $ sudo vi /var/www/html/mapleyu.ddns.net/public_html/index.html
     ```
     ```
     $ sudo vi /var/www/html/sundial.ddns.net/public_html/index.html
     ```
    3. 建立Virtual Host虛擬主機文件 (位於 /etc/apache2/sites-available/ 中，告訴Apache網頁伺服器如何響應各種網域請求，修改virtualhost標籤的兩段
    ```
    $ sudo vi /etc/apache2/sites-available/000-default.conf
    <VirtualHost *:8080>
    ServerName mapleyu.ddns.net
    DocumentRoot /var/www/html/mapleyu.ddns.net/public_html
    ErrorDocument 404 http://mapleyu.ddns.net/error.html
    <Directory "/var/www/html/mapleyu.ddns.net/public_html">
        AuthType Basic
        AuthName "Restricted Area"
        AuthUserFile /var/www/html/.htpasswd
        Require valid-user
    </Directory>
    <Directory /var/www/mapleyu.ddns.net/public_html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    <Directory /var/www/mapleyu.ddns.net/public_html/bob>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    </VirtualHost>
    <VirtualHost *:80>
    ServerName sundial.ddns.net
    DocumentRoot /var/www/html/sundial.ddns.net/public_html
    </VirtualHost>
    <VirtualHost *:80>
    #後面不變
    ```
* 404轉址如上ErrorDocument
* 改埠號如上改000-default.conf變8080，且修改ports.conf要Listen8080
* 增加使用者驗證，要改同上面000-default.conf第一段Directory標籤
```
$sudo apt-get install apache2-utils
$sudo htpasswd -c /etc/apache2/.htpasswd username001
```

* 建立使用者網站如http://你的主機名稱/~bob/ 呈現網頁內容，要改同上面000-default.conf第二與第三段Directory標籤
```
#啟動userdir模組
$ sudo a2enmod userdir
$ sudo adduser bob
$ mkdir -p /home/bob/public_html
$ echo Hi bob > index.html
$ chmod 777 /home/bob
$ sudo systemctl restart apache2
```

    4. 啟用新的虛擬主機文件
    ```
    sudo a2ensite 000-default.conf
    sudo systemctl reload apache2
    ```




#### 第二題:
```
$ systemctl start mariadb.service
```
#### 第三題:
```
https://www.linuxprobe.com/ubuntu-configure-nfs.html
https://www.myfreax.com/how-to-install-and-configure-samba-on-ubuntu-20-04how-to-install-and-configure-samba-on-ubuntu-20-04/
https://magiclen.org/ubuntu-server-samba/
```
### 進階專案1
1. [DB]滿足各組主網站資料庫需求
2. [SCRIPT]使用 python 撰寫針對某帳號每日自動換密碼腳本。(需定義密碼表規範)
3. [PWC]將日前 python 爬蟲專案一Technews獲取的資料，匯入各組主網站資料庫以自己命名的資料庫中

* 第二題：Ubuntu 修改密碼
1. 在python程式中要執行linux的指令可以import subprocess。
2. 產生亂數可以imort random，使用random.choice()的方法。
3. 要產生n位數的字串可以使用.join

```py=
#changepswd.py
import subprocess
import random
import string
import json

#產生長度為參數len，且每一個字元為亂數產生的密碼
def generatePassword(len):
    chart = string.ascii_letters + string.digits #所有英文符號跟數字
    password = ''.join(random.choice(chart) for _ in range(len))
    return password

#修改user的密碼為newPasswd
def changePassword(user, newPasswd):
    command = f"echo '{user}:{newPasswd}' | sudo chpasswd"
    subprocess.run(command, shell=True)

#產生num組密碼，每組密碼長度為passwdLen
def genPasswdTable(num, passwdLen):
    passwords = {}
    for i in range(num):
        password = generatePassword(passwdLen)
        passwords[f"Password {i+1}"] = password
    return passwords

username = 'user1'      #使用者帳號
num = 7       #密碼表內密碼組數
passwdLen = 6    #密碼長度

#生成密碼表，寫入檔案
passwordTable = genPasswdTable(num, passwdLen)
with open('passwd.json', 'w', encoding='utf-8') as fp:
    json.dump(passwordTable, fp, indent=4, ensure_ascii=False)

#生成密碼
selectedPasswd = random.choice(list(passwordTable.values()))

#修改密碼
changePassword(username, selectedPasswd)
result = f"使用者 {username} 的密碼已改為: {selectedPasswd}"

#密碼修改紀錄 (path需自行調整)
with open('/home/admin1/changepasswd/passwdlog.json', 'a', encoding='utf-8') as fp:
    json.dump(result, fp, indent=4, ensure_ascii=False)
    fp.write('\n')
```
Output:
![](https://hackmd.io/_uploads/BJzXAzbB2.png)

接著把此python檔案改成執行檔，並執行crontab -e將排成寫入
![](https://hackmd.io/_uploads/rkgGRCGWB3.png)
![](https://hackmd.io/_uploads/S1nuym-B3.png)


* 第三題：先到Mariadb建立資料庫、資料表
```
CREATE SCHEMA `technews` ;
CREATE TABLE `technews`.`news_contents` (
  `index` INT NOT NULL AUTO_INCREMENT,
  `category` VARCHAR(45) NULL,
  `title` VARCHAR(100) NULL,
  `url` VARCHAR(200) NULL,
  `sum` INT NULL,
  `spotlist` INT NULL,
  PRIMARY KEY (`index`));
```
```py=
import requests
from bs4 import BeautifulSoup
import json
import pymysql

url = "https://technews.tw/"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
#找到要爬的整塊區塊
paragraph = soup.find("ul", class_="screen")

#要放入MySQL的前置作業
db_settings = {
    "host": "127.0.0.1",
    "port": 3366,
    "user": "root",
    "password": "123456",
    "db": "technews",
    "charset": "utf8"
}
# 建立Connection物件
connect_db   = pymysql.connect(**db_settings)

paraAll=[]

#先找到第一筆資料
para1 = paragraph.find("li", class_="block2014")
category = para1.find("div",class_="cat01").text
sum_title = para1.find("h3").text
sum_title_url = para1.find("a").get("href")
spotlist1_title = para1.find("li", class_="spotlist").find("a").text
spotlist1_url = para1.find("li", class_="spotlist").find("a").get("href")
spotlist2_title = para1.find("li", class_="spotlist").findNextSibling("li").find("a").text
spotlist2_url = para1.find("li", class_="spotlist").findNextSibling("li").find("a").get("href")
spotlist3_title = para1.find("li", class_="spotlist").findNextSibling("li").findNextSibling("li").find("a").text
spotlist3_url = para1.find("li", class_="spotlist").findNextSibling("li").findNextSibling("li").find("a").get("href")
paraAll.append({"category": category,
                "sum_title": sum_title,
                "sum_title_url": sum_title_url,
                "spotlist": [{"title": spotlist1_title,
                               "url": spotlist1_url},
                             {"title": spotlist2_title,
                               "url": spotlist2_url},
                             {"title": spotlist3_title,
                               "url": spotlist3_url}
                             ]})
#insert 到 mariadb
values = [
            (category, sum_title, sum_title_url, 1, 0),
            (category, spotlist1_title, spotlist1_url, 0, 1),
            (category, spotlist2_title, spotlist2_url, 0, 2),
            (category, spotlist3_title, spotlist3_url, 0, 3)
        ]
with connect_db.cursor() as cursor:
    for value in values:
        sql = f'insert into technews.news_contents (category, title, url, sum, spotlist) values {value};'
        cursor.execute(sql)
        connect_db.commit()

#再找第二到八筆資料
para2 = para1.findNextSibling("li", class_="block2014")
for i in range(7):
    category = para2.find("div",class_="cat01").text
    sum_title = para2.find("h3").text
    sum_title_url = para2.find("a").get("href")
    spotlist1_title = para2.find("li", class_="spotlist").find("a").text
    spotlist1_url = para2.find("li", class_="spotlist").find("a").get("href")
    spotlist2_title = para2.find("li", class_="spotlist").findNextSibling("li").find("a").text
    spotlist2_url = para2.find("li", class_="spotlist").findNextSibling("li").find("a").get("href")
    spotlist3_title = para2.find("li", class_="spotlist").findNextSibling("li").findNextSibling("li").find("a").text
    spotlist3_url = para2.find("li", class_="spotlist").findNextSibling("li").findNextSibling("li").find("a").get("href")
    if para2:
        paraAll.append({"category": category,
                        "sum_title": sum_title,
                        "sum_title_url": sum_title_url,
                        "spotlist": [{"title": spotlist1_title,
                                      "url": spotlist1_url},
                                     {"title": spotlist2_title,
                                      "url": spotlist2_url},
                                     {"title": spotlist3_title,
                                      "url": spotlist3_url}
                                     ]})
        values = [
            (category, sum_title, sum_title_url, 1, 0),
            (category, spotlist1_title, spotlist1_url, 0, 1),
            (category, spotlist2_title, spotlist2_url, 0, 2),
            (category, spotlist3_title, spotlist3_url, 0, 3)
            ]
        with connect_db.cursor() as cursor:
            for value in values:
                sql = f'insert into technews.news_contents (category, title, url, sum, spotlist) values {value};'
                cursor.execute(sql)
                connect_db.commit()
        i += 1
        para2 = para2.findNextSibling("li", class_="block2014")
    else:
        break

connect_db.close()

with open('TechNews2.json','w',encoding="utf-8") as f:
    json.dump(paraAll, f, ensure_ascii=False, indent=4)

```
Output:
![](https://hackmd.io/_uploads/HyCVx--Bh.png)

### 進階專案2：
1. 將[海量圖檔](https://drive.google.com/drive/folders/1vWe_UioA0vzZwKeMfUWLAeqQLgLkAbWN?usp=sharing)進行路徑編列，於資料庫中建立表格，提供檔名及路徑查詢（台灣金融單位票據憑證專案皆須使用）
2. 使用python將[IDP日誌](https://drive.google.com/drive/folders/1z7R4ep_G0cIxWLesv3Noe9IyMHjpcnmf?usp=sharing
)進行數據處理，整理日期、時間、來源ip、來源port、目標ip、目標port、事件名稱等欄位，自動化讀取目標資料夾檔案後，增加至資料庫中（常見於大型企業資料分析師實機面試題目）
3.

第一題
```
#在Mariadb建立資料表
create database img
use img
create table img1(name VARCHAR(30),path  VARCHAR(50));
```
```py=
#img_to_mariadb.py
import os
import pymysql

#連接 MariaDB
conn = pymysql.connect(
    user='admin1',
    password='123456',
    host='127.0.0.1',
    database='img'
)
cursor = conn.cursor()

#圖像路径
image_path = '/home/admin1/Vol_001/'

#遍歷路徑中檔案
dirs =  os.listdir(image_path)
for filename in dirs:
    print(filename)
    if filename.endswith('.jpg'):
    #將文件名插入資料表中
        cursor.execute("INSERT INTO img1 (name, path) VALUES (%s, %s)", (filename, image_path))

#提交更改並關閉
conn.commit()
conn.close()
```
Output:
![](https://hackmd.io/_uploads/SkO4qffSn.png)


第二題：
先建立資料庫、資料表
```
CREATE database `diarylog` ;
CREATE TABLE `diarylog`.`idp` (
  `index` INT NOT NULL AUTO_INCREMENT,
  `priority` VARCHAR(45) NULL,
  `datetime` DATETIME NULL,
  `user` VARCHAR(45) NULL,
  `event` VARCHAR(200) NULL,
  `source_ip` VARCHAR(45) NULL,
  `insert_datetime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`index`)
);
```

```py=
import csv
import pymysql
import pandas as pd
import re

# 讀取CSV檔案
source_file = 'syslog_2023-5-17-9_2_54.csv'

with open(source_file, 'r', encoding='utf-8') as file:
    reader = csv.reader(file)
    headers_ = next(reader)  # 獲取CSV標題列
    header = next(reader)  # 獲取CSV標題列
    listContents = list(reader)

header.pop()
df = pd.DataFrame(listContents, columns=header)
df['ip'] = None

for i in range(df.shape[0]):
    if df['優先層級'][i] == 'Warning':
        ip_start = df['事件'][i].find(' [') + 2
        ip_end = df['事件'][i].find('] ')
        ip = df['事件'][i][ip_start:ip_end]
        df.at[i, 'ip'] = ip
#使用正則表達式移除事件中的[ip]字段，\d+ 表示一個或多個數字，\. 表示句點
df['事件'] = df['事件'].apply(lambda x: re.sub(r' \[\d+\.\d+\.\d+\.\d+\]', '', x))
df['時間'] = pd.to_datetime(df['時間'])
df = df.drop("日誌", axis=1)
#df.to_csv('test123.csv', index=False)

#要放入MySQL的前置作業
db_settings = {
    "host": "127.0.0.1",
    "port": 3366,
    "user": "root",
    "password": "123456",
    "db": "diarylog",
    "charset": "utf8"
}

# 建立Connection物件
connect_db = pymysql.connect(**db_settings)

with connect_db.cursor() as cursor:
    for i in range(df.shape[0]):
        sql = """
        INSERT INTO diarylog.idp (priority, datetime, user, event, source_ip) 
        VALUES ('{}', '{}', '{}', '{}', '{}');
        """.format(df.at[i, '優先層級'], df.at[i, '時間'], df.at[i, '使用者'], df.at[i, '事件'], df.at[i, 'ip'])
        cursor.execute(sql)
    connect_db.commit()

connect_db.close()
```
Output:
![](https://hackmd.io/_uploads/H1HFELGSh.png)


第三題

---

### 補充
#### 如何在Apache上增加不同網域，指向不同網頁。
https://pala.tw/subdomain-apache-virtual-host/
https://ui-code.com/archives/271
https://hackmd.io/@Flion/SJzQrURX2#%E5%8F%83%E8%80%83%E7%B6%B2%E7%AB%99


###### tags: `python` `爬蟲` `apache` `專案一` `mariadb` `LinuxCCP`