一、Linux / Shell

tee 双向输出 + head/tail 日志查看

1. tee命令:从标准输入读取数据,同时输出到标准输出(屏幕) 和一个或多个文件

tee [选项] [文件...]

-a, --append				追加到文件末尾,而不是覆盖
-i, --ignore-interrupts		忽略中断信号
--help						显示帮助信息
--version					显示版本信息

1.1 基本用法:同时输出到屏幕和文件

//将 echo 的输出同时显示在屏幕并写入 file.txt
echo "Hello World" | tee file.txt

//输出到多个文件
echo "Hello" | tee file1.txt file2.txt file3.txt

1.2 追加模式:不覆盖原有内容

echo "New line" | tee -a existing.log

1.3 隐藏屏幕输出

//只想写入文件,不想看屏幕输出
echo "Secret" | tee secret.txt > /dev/null

1.4 配合 sudo 写入受保护文件

//向需要root权限的文件写入内容
echo "127.0.0.1 example.com" | sudo tee -a /etc/hosts

1.5 在管道中同时保存中间结果

//统计命令执行过程中某个阶段的数据
cat large_file.txt | tee temp.txt | grep "error" | wc -l
//temp.txt 保存了完整内容,便于后续分析

1.6 进程替换:同时给多个命令提供数据

//一份数据同时给两个不同的命令处理
echo -e "apple\nbanana\ncherry" | tee >(sort) >(wc -l) > /dev/null

2. head 命令:输出文件的开头部分,默认显示前 10 行

head [选项] [文件...]

-n N, --lines=N			显示前 N 行
-c N, --bytes=N			显示前 N 个字节
-q, --quiet, --silent	不显示文件名标题(多文件时)
-v, --verbose			总是显示文件名标题
--help					显示帮助信息

2.1 基本用法:显示前10行

//默认显示前10行
head file.txt

//指定显示前20行
head -n 20 file.txt
head -20 file.txt          # 简写形式

2.2 显示前 N 个字节

//显示前100个字节
head -c 100 file.txt

//显示前1KB(1024字节)
head -c 1024 file.txt

2.3 处理多个文件

//显示多个文件的前5行,会自动显示文件名标题
head -n 5 file1.txt file2.txt file3.txt

# 输出示例:
# ==> file1.txt <==
# line1
# line2
# ...
# ==> file2.txt <==
# line1
# ...

//禁止显示文件名标题
head -q -n 5 file1.txt file2.txt

2.4 与其他命令组合

//查看进程列表的前10个
ps aux | head -10

//查看日志文件的前50行
head -50 /var/log/syslog

//排除最后100行,只显示前面的内容(结合 tail 使用)
head -n -100 file.txt   # 显示除了最后100行之外的所有内容

2.5 负数的特殊用法

//显示除了最后5行之外的所有行
head -n -5 file.txt

//显示除了最后20字节之外的所有内容
head -c -20 file.txt

3. tail 命令:输出文件的结尾部分,默认显示后 10 行

tail [选项] [文件...]

-n N, --lines=N			显示最后 N 行
-c N, --bytes=N			显示最后 N 个字节
-f, --follow			实时跟踪文件新增内容
-q, --quiet, --silent	不显示文件名标题
-v, --verbose			总是显示文件名标题

3.1 基本用法:显示最后10行

//默认显示最后10行
tail file.txt

//显示最后20行
tail -n 20 file.txt
tail -20 file.txt          # 简写形式

3.2 实时监控日志(最常用)

//实时跟踪日志文件的新增内容
tail -f /var/log/syslog

//实时跟踪,并显示最后50行
tail -n 50 -f app.log

//更友好的显示,加上行号
tail -f access.log | nl

3.3 处理日志轮转(-F 参数)

//即使文件被重命名或轮转,也能继续跟踪
tail -F /var/log/nginx/access.log

//-F 比 -f 更强大:
//- 文件被删除/重命名后会重新打开
//适用于 logrotate 等日志轮转工具

3.4 显示最后 N 个字节

//显示最后200个字节
tail -c 200 file.txt

//显示最后1KB
tail -c 1024 log.txt

3.5 从第 N 行开始显示

//从第15行开始显示(包括第15行)
tail -n +15 file.txt

//从第100行开始显示到末尾
tail -n +100 large_file.txt

3.6 组合 tail 和 head 提取中间段落

//显示第50-60行(先取前60行,再取最后11行)
head -60 file.txt | tail -11

//显示第100行到文件末尾
tail -n +100 file.txt

//显示第1-100行(排除第101行之后)
head -100 file.txt

3.7 多文件监控

//同时监控多个日志文件
tail -f error.log access.log

# 输出会标注文件来源:
# ==> error.log <==
# error message...
# ==> access.log <==
# access message...

3.8 配合 PID 自动退出

//监控日志,当进程 1234 结束时,tail 也退出
tail -f --pid=1234 app.log

4. 三个命令对比总结


特性		 tee		     	     head		    	   tail
主要用途	     数据分流/保存	         查看文件开头	       查看文件结尾
默认行数	     无(处理所有输入)   	 1010 行
是否修改文件	 写入文件(不修改原内容)	 只读	               只读
实时监控	     否	                     否	                   是(-f/-F)
常见场景  	 保存日志、sudo 写入	     预览文件、查看配置  	   监控日志、查看最新数据

5. 任务:
对 login.log 执行:

1. 提取 uid(第 2 列)
2. 去重统计
3.同时输出到屏幕 并 保存到 uid_stat.log
4.只显示前 5 条

//login.log
2025-04-09 10:00:00,uid100,login_success
2025-04-09 10:01:00,uid101,login_fail
2025-04-09 10:02:00,uid100,login_success
cut -d',' -f2 login.log | sort | uniq -c | sort -nr | tee uid_stat.log | head -5

大数据排查常用:实时看日志 + 留存记录

二、SQL

511. 游戏玩法分析I
在这里插入图片描述

SELECT
  A.player_id,
  MIN(A.event_date) AS first_login
FROM
  Activity A
GROUP BY
  A.player_id;

分组取每组最小日期 = 首次登录日期
多字段 IN 子查询精准匹配首次登录记录
典型场景:用户首设备、首单、首次访问

1596. 每位顾客最经常订购的商品
在这里插入图片描述

SELECT activity_date AS login_date, COUNT(DISTINCT user_id) AS user_count
FROM Traffic
WHERE activity = 'login'
GROUP BY user_id, activity_date
HAVING MIN(activity_date) = activity_date;

先筛选 login 行为
按用户 + 日期分组,只保留最小登录日期
按日期统计当日新增登录用

1069. 产品销售分析
在这里插入图片描述

SELECT p.product_name, s.product_id, s.year, s.quantity, s.price
FROM Sales s
JOIN Product p ON s.product_id = p.product_id
WHERE (s.product_id, s.year) IN (
    SELECT product_id, MIN(year)
    FROM Sales
    GROUP BY product_id
);

关联产品表获取名称
子查询找到每个产品最早销售年份
主表匹配年份,取出首年全部销售记录

三、PySpark 核心新内容

视图与函数 + 多维度排序 + 数据采样 + 性能小优化

from pyspark.sql import SparkSession
from pyspark.sql import functions as F

spark = SparkSession.builder \
    .master("local[*]") \
    .appName("day10") \
    .getOrCreate()

data = [
    (1, "click", 100, "2025-01-01"),
    (1, "buy", 200, "2025-01-01"),
    (2, "view", 50, "2025-01-02"),
    (3, "click", 80, "2025-01-01"),
]
df = spark.createDataFrame(data, ["uid", "event", "cost", "dt"])

# ==================== 新知识点1:创建全局临时视图 ====================
df.createOrReplaceTempView("user_log")
# SQL查询
spark.sql("select uid, sum(cost) from user_log group by uid").show()

# ==================== 新知识点2:多列排序 ====================
df.orderBy(F.desc("cost"), F.asc("uid")).show()

# ==================== 新知识点3:数据采样(大数据排查用) ====================
df.sample(withReplacement=False, fraction=0.5, seed=123).show()

# ==================== 新知识点4:withColumnRenamed 重命名 ====================
df.withColumnRenamed("cost", "amount").show()

spark.stop()

createOrReplaceTempView 建临时视图

多字段组合排序

sample 数据采样

字段重命名

四、算法

LeetCode 209. 长度最小的子数组
滑动窗口 O (n) 最优解
理解左右指针收缩逻辑
对比前缀和 O (n log n) 思路

def minSubArrayLen(target, nums):
    left = total = 0
    min_len = float('inf')
    for right in range(len(nums)):
        total += nums[right]
        while total >= target:
            min_len = min(min_len, right-left+1)
            total -= nums[left]
            left += 1
    return min_len if min_len != float('inf') else 0

更多推荐