Ubuntu应用场景

予早 2026-04-30 23:53:27
Categories: Tags:

总结Ubuntu中常用操作场景

Ubuntu 软件源更换为清华源

cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak
Types: deb
URIs: https://mirrors.tuna.tsinghua.edu.cn/ubuntu/
Suites: noble noble-updates noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
apt-get update

Ubuntu 机器基础准备

安装 JDK

sudo apt install -y openjdk-17-jdk

为 Ubuntu 系统创建具有 sudo 的一般用户

# 新增用户
sudo adduser ubuntu
# 将用户加入 sudo 组
sudo usermod -aG sudo ubuntu

安装 tmux

sudo apt update
sudo apt install tmux -y

Linux 安装配置执行 APP SOP

新建 APP 隔离运行用户

sudo useradd -r -s /usr/sbin/nologin -d /nonexistent -U -M myapp
# -r 系统账号  -s nologin 禁止登录  -U 同时建组  -M 不建 home

解压软件到及创建标准化目录

myapp.py

#!/usr/bin/env python3
"""
极简 Web 服务器 —— 返回指定配置文件的全部内容(日志级别对齐版)
用法:
    python mini_server.py \
        --host 0.0.0.0 \
        --port 8080 \
        --config /path/to/file.txt \
        --log-level INFO
"""
import argparse
import logging
from http.server import BaseHTTPRequestHandler, HTTPServer


def setup_logging(level: str) -> None:
    """初始化日志格式与级别,级别固定 8 字符宽度左对齐"""
    logging.basicConfig(
        level=getattr(logging, level.upper(), logging.INFO),
        format="[%(asctime)s] [%(levelname)-8s] %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
    )


def read_file(path: str) -> bytes:
    """读取配置文件全部内容,以二进制返回"""
    logging.debug("Reading config file: %s", path)
    with open(path, "rb") as f:
        return f.read()


class Handler(BaseHTTPRequestHandler):
    def __init__(self, file_path: str, *args, **kwargs):
        self.file_path = file_path
        super().__init__(*args, **kwargs)

    def do_GET(self):
        """仅支持 GET,返回配置文件内容"""
        logging.info("GET %s from %s", self.path, self.client_address[0])
        try:
            body = read_file(self.file_path)
            self.send_response(200)
            self.send_header("Content-Type", "text/plain; charset=utf-8")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            logging.debug("Response sent (%d bytes)", len(body))
        except Exception as e:
            logging.exception("Error handling GET")
            self.send_error(500, str(e))

    def log_message(self, fmt, *args):
        """覆盖父类日志,统一到 logging 模块"""
        logging.info("%s - %s", self.address_string(), fmt % args)


def main():
    parser = argparse.ArgumentParser(description="myapp")
    parser.add_argument("--host", default="127.0.0.1", help="监听 IP (默认 127.0.0.1)")
    parser.add_argument("--port", type=int, default=8000, help="监听端口 (默认 8000)")
    parser.add_argument("--config", required=True, help="配置文件路径")
    parser.add_argument(
        "--log-level",
        default="INFO",
        choices=["DEBUG", "INFO", "WARNING", "ERROR"],
        help="日志级别 (默认 INFO)",
    )
    args = parser.parse_args()

    setup_logging(args.log_level)

    handler = lambda *a, **kw: Handler(args.config, *a, **kw)
    server = HTTPServer((args.host, args.port), handler)

    logging.info("Serving on http://%s:%d/ (Ctrl-C 退出)", args.host, args.port)
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        logging.info("Shutting down")


if __name__ == "__main__":
    main()
# 1. 创建目录
mkdir -p /usr/local/myapp /etc/myapp /var/lib/myapp /var/log/myapp /run/myapp

# 2. 提前给属主(保证后续解压继承)
chown -R myapp:myapp /usr/local/myapp /etc/myapp /var/lib/myapp /var/log/myapp /run/myapp

# 3. 解压
tar -zxvf myapp.tar.gz -C /usr/local/myapp

# 4. 权限
sudo chmod -R 755 /usr/local/myapp /etc/myapp /run/myapp
sudo chmod -R 750 /var/lib/myapp /var/log/myapp

APP 配置文件

myapp.cfg

Welcome to myapp!!!
chmod 640 /etc/myapp/myapp.cfg

systemd 单元配置

/etc/systemd/system/myapp.service

# /etc/systemd/system/myapp.service

[Unit]
# 服务描述
Description = myapp
# 依赖
# network-online.target 是网络在线
# nss-lookup.target     是 NSS 就绪
# 弱依赖,服务启动之前启动但启动失败不会影响服务本身。
Wants = network-online.target
# 强依赖,服务在强依赖之后启动,若强依赖启动失败则服务无法启动
After = network-online.target nss-lookup.target

# 30 秒内最多重启 3 次
StartLimitIntervalSec = 30
StartLimitBurst = 3

[Service]
# 启动方式
Type = simple
# 运行用户
User = myapp
# 运行组
Group = myapp
# 启动执行命令
ExecStart = /usr/bin/python3 /usr/local/myapp/myapp.py \
            --host 0.0.0.0 --port 8080 \
            --config /etc/myapp/myapp.cfg \
            --log-level DEBUG
# 平滑重载配置,此处是发送 SIGHUP 信号,如何重载需要由应用程序处理该型号并实现具体逻辑
ExecReload = /bin/kill -HUP $MAINPID
# 异常退出才重启(exit 非 0)
Restart = on-failure
# 失败后 5 秒再试
RestartSec = 5s

# ----------  安全加固  ----------
# 禁止进程及其子进程提权
NoNewPrivileges = true
# 除明确列出目录外,整个文件系统只读
ProtectSystem = strict
# 禁止访问 /home、/root、/run/user
ProtectHome = true
# 允许写日志、数据、运行时
ReadWritePaths = /var/log/myapp /var/lib/myapp /run/myapp

[Install]
# 开机随多用户模式启动
WantedBy = multi-user.target

使用 systemctl 控制 APP 声明周期

# 重新加载配置
sudo systemctl daemon-reload

sudo systemctl status myapp

# 设置开机自启
sudo systemctl enable --now myapp.service

# 看状态/日志
sudo systemctl status myapp
sudo journalctl -u myapp -f
elasticsearch-create-enrollment-token -s kibana

简单授权过程

sudo chown -R ubuntu:ubuntu /usr/local/myapp
sudo chmod -R 750 /usr/local/myapp