---
# System prepended metadata

title: web server 筆記
tags: [nginx, flask, react, web]

---

# web server 筆記
## 使用的框架
伺服器使用 Nginx
前端使用 react, node.js, npm, JS語言
後端使用 flask


## Flask相關指令


開始 Flask
```
sudo systemctl start flask.service
```
開機啟動 Flask
```
sudo systemctl enable flask.service
```
查看 Flask 狀態
```
sudo systemctl status flask.service
```
重啟 Flask
```
sudo systemctl restart flask.service
```

使用 flask 啟動程序
```
flask run
flask run --debug
flask run --host=0.0.0.0 --port=5000
```

`sudo systemctl daemon-reload`
你新增或刪除了 Systemd 的服務文件後需要重須啟動。
注意：這不會立即啟動或重啟服務，只是讓 Systemd 更新服務的配置。

`sudo lsof -i :5000`
查看在 Port 5000 上運行的服務

### Notice
不管何時，如果你嘗試 debug Flask Server。使用 curl 去嘗試是個好主意。

如果跑在Port 5000，通過本地訪問
```
curl http://127.0.0.1:5000
```

如果使用 Nginx 反向代理，使用
```
curl http://141.147.150.224/service5000/
```
另一個例子
```
curl http://141.147.150.224/service5000/api/get_dashboard_data
```
嘗試重開
```
sudo systemctl restart flask.service
```

### 配置後台運行
```
sudo vim /etc/systemd/system/flask.service
````
:::success
```
[Unit]
Description=Flask App
After=network.target

[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu
ExecStart=/usr/bin/python3 /home/ubuntu/app.py
Restart=always

[Install]
WantedBy=multi-user.target
```
:::
然後重開
```
sudo systemctl daemon-reload
sudo systemctl restart flask.service
```





### `python3 app.py`
當 Server 出現問題時，無法跑起來。可以手動跑跑看，這樣會出現錯誤信息。

## react 指令

### 套件 `create-react-app`
可以幫你生出一套框架，並安裝一些東西。


## 各種安裝指令
安裝 Flask
```
pip install flask flask-cors
```
安裝 react 的 axios，一個Http庫
```
npm install axios
```

## 防火牆指令
允許Port 5000
```
sudo ufw allow 5000
```
不允許 Port 5000
```
sudo ufw deny 5000
```
查看防火牆
```
sudo ufw status
```
重啟防火牆
```
sudo ufw reload
```


## Nginx 安裝
```
sudo apt update && sudo apt upgrade -y
sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
```





## 啟動 pyhton 虛擬環境
```
sudo apt install python3-venv
source venv/bin/activate
python3 -m venv venv
```
最後一個venv是名稱，可以自己改。

## Nodejs 安裝
安裝 Node Package Manager
```
sudo apt install npm

node -v
建議版本要是Node 14 or Higher。
npm -v
```

更新 Node.js
```
sudo apt update
sudo apt upgrade
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
node -v
npm -v
```

`npm install react-router-dom`
路由解決方案，用於解決頁面切換


```
npm install @tanstack/react-query --legacy-peer-deps
npm install @tanstack/react-query-devtools --legacy-peer-deps
```
安裝 React Query
## nodejs 指令

```
sudo npm isntall
```
sudo npm install 會尋找文件 package.json 去下載。
```
npm run build
```
使用 npm run build 來構件靜態網站，類似於編譯。

```
sudo chown -R $USER:$USER ~/.npm
```
修改 ~/.npm 權限，從root擁有變為$USER擁有




固定會議室
https://meet.google.com/aas-rfvw-afo




觀測cpu
cat /proc/cpuinfo | grep "MHz"
watch -n 1 "grep 'MHz' /proc/cpuinfo"

## 框架內容

`package.json`
一份 json文件，有一些配置資料。使用 `npm install`來安裝配置。

`package-lock.json`
一份18k行的json文件，儲存套件資料。



`public/index.html`
主要的html。

`src/index.js`
使用了 App, styles.css 的文件。

`src/styles.css`
一個 css 設定檔。

`src/App.js`
src/components/FileUpload.js


## 以下未整理

伺服器傳送
const exectureable = [
  { title: 'Cabbage', executable_name: 'Asd', input_num: 3 },
];

伺服器接收
const exectureable = [
  { executable_name: 'Asd', input_num: 3, input_data1: 1, input_data2: 2, input_data3: 3 },
];

# 變成 string
```
 <pre>{JSON.stringify(data, null, 2)}<\pre> 


<script>
      async function fetchData() {
        try {
          const response = await fetch("http://141.147.150.224/service5000/api/data");

          if (!response.ok) {
            throw new Error("Network response was not ok");
          }
          const data = await response.json();
          document.getElementById("output").innerText = data.message;
        } catch (error) {
          document.getElementById("output").innerText = `Error: ${error.message}`;
        }
      }

 </script>
  ```
 
 與伺服器進行數據傳輸的函數的命名規則
get 取得
fetch 取得
post 提交
update 更新
delete 刪除
 
/api/save_dashboard_data
/api/get_dashboard_data
/api/upload_executable

使用 curl
server接收
```
curl -X POST -H "Content-Type: application/json" \
     -d '{"key": "value"}' \
     http://localhost:5000/save_dashboarddata
```

server傳送
```
curl http://localhost/service5000/api/get_dashboard_data
```




後端api驗證用戶
const handleLogin = async () => {
  const response = await fetch('/api/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, password }),
  });

  const data = await response.json();

  if (response.ok && data.token) {
    localStorage.setItem('token', data.token); // 保存 token
    navigate('/dashboard');
  } else {
    alert('Login Failed');
  }
};

Mutation更新數據
import React from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';

const postData = async (newData) => {
  const response = await fetch('/api/data', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(newData),
  });
  if (!response.ok) {
    throw new Error('Failed to post data');
  }
  return response.json();
};

const AddDataButton = () => {
  const queryClient = useQueryClient();

  const mutation = useMutation(postData, {
    onSuccess: () => {
      queryClient.invalidateQueries(['serverData']); // 更新數據後重新拉取
    },
  });

  const handleClick = () => {
    mutation.mutate({ name: 'New Item' });
  };

  return (
    <button onClick={handleClick} disabled={mutation.isLoading}>
      {mutation.isLoading ? 'Adding...' : 'Add Data'}
    </button>
  );
};

export default AddDataButton;


當前的組件和函數
<FileUpload SERVER_IP={SERVER_IP} />
const postData = async (url, newData) => {
const AddExecutableButton = () => {
const DashboardPage = () => {
async function fetchDashboardData () {
const LoginPage = () => {
const dashboard_component = ({ title, executable_name, input_num }) => {

一開始會到login page
然後到dashboard，dashboard會請求資料，並使用dashboard_component和FileUpload渲染。
當點擊FileUpload，進入新畫面，有Title，輸入框，參數數量，輸入框，可執行檔路徑，傳送資料
