解决 linux 命令行光标莫名消失
2021-05-16 tech linux 1 mins 148 字

说来也是奇怪。我感觉应该是我在 gnome-tweak 开启过多东西的原因,里面有啥方法把光标关掉然后没有恢复吧。
直接手动设置吧:
echo -e "\033[?25h" # 显示光标
将其设置到 .bashrc 或者 .zshrc 里:
alias ts='echo -e "\033[?25h"'

说来也是奇怪。我感觉应该是我在 gnome-tweak 开启过多东西的原因,里面有啥方法把光标关掉然后没有恢复吧。
直接手动设置吧:
echo -e "\033[?25h" # 显示光标
将其设置到 .bashrc 或者 .zshrc 里:
alias ts='echo -e "\033[?25h"'


首先进入BIOS 的设置主界面,找到[POWER MANAGEMENT SETUP],再找到[PWR Lost Resume State] 或者 [AC Recovery],这一项有三个选择项。

CPU 动态节能技术用于降低服务器功耗,通过选择系统空闲状态不同的电源管理策略,可以实现不同程度降低服务器功耗,更低的功耗策略意味着 CPU 唤醒更慢对性能影响更大。
对于对时延和性能要求高的应用,需要在服务器 BIOS 中修改电源管理为 Performance,从而关闭 CPU 的动态调节功能,禁止 CPU 休眠,把 CPU 频率固定到最高。
更多关于主机电源管理的内容,可以参考我前一篇文章《一些 bios 配置优化的备忘》— C-State P-State。我们既可以在bios进行设置,也可以在OS进行设置。具体到 linux 操作系统,就是通过 cpufreq 进行配置。
grep -E '^model name|^cpu MHz' /proc/cpuinfo
在我本机可以看到,主频与实际运行的主频是不一致的:
时间1:

时间二:

cpufreq 是一个动态调整 cpu 频率的模块,系统启动时生成一个文件夹 /sys/devices/system/cpu/cpu0/cpufreq/,里面有几个文件,其中 scaling_min_freq 代表最低频率,scaling_max_freq 代表最高频率,scalin_governor 代表 cpu 频率调整模式,用它来控制 CPU 频率。
# 查看当前的调节器
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
conservative
for CPUFREQ in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
[ -f $CPUFREQ ] || continue
echo -n performance > $CPUFREQ
done
再查看当前调节器
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

最后确认 cpu 主频已定格在最高频率,发现已全部运行在最高频率。
grep -E '^model name|^cpu MHz' /proc/cpuinfo

这个配置重启后会失效。如果需要持久化,可以设置开机自动运行本命令,或通过修改bios配置达到目的。

本文参考了华为的文档《FusionCompute V100R005C10 软件安装指南 02》,以下是我的一些笔记,不同设备的某些选项可能不同,仅供参考。
使CPU支持多线程,提升CPU性能。


CPU硬件防病毒技术,亦称作NX或XD功能。
“Execute Disable Bit”是Intel在新一代处理器中引入的一项功能,开启该功能后,可以防止病毒、蠕虫、木马等程序利用溢出、无限扩大等手法去破坏系统内存并取得系统的控制权。
speedstep 技术是通过降低 cpu 运行主频来达到降低功耗的技术,CPU 工作模式切换技术。
新款服务器写作 EIST(智能降频技术)。
· SpeedStep (GV1.1) 最早被引入奔腾M III,也就是笔记本电脑版奔腾。原理十分简单:双模式工作–全功率模式和省电模式。插上电源时,全速工作;电池供电时,已几乎一半主频工作(当然可以手动切回全速模式)。
· Enhanced SpeedStep (GV2.1) 加入了根据工作量自动在两个主频间切换的功能。实际上CPU就可以工作在三种模式下了:省电模式,性能优先模式和自动模式。
· Enhanced SpeedStep (GV2.2) 加入了Deep Alert mode。可以已更低的电压工作在省电模式下。
·EIST(Enhanced Intel SpeedStep Technology,GV3) 这版做出了巨大的改进,从此不再是只有两种频率可以选择了,而是有一个范围可以选择,通常以100MHz为一个步进(Step)。
OS 主导了在整个 EIST 在的各个频率的切换,只有它最了解工作量。同时EIST要工作,硬件,固件和OS三方缺一不可。
所以这个配置既可以在 BIOS 配置,又可以在操作系统层面配置,当然在BIOS层配置最好。
如果BIOS已经关闭了 speedstep 或者 EIST,那C-State P-State的配置实际上也没所谓了(原理上是如此)。
Intel CPU是 EIST 可以工作的硬件基础。它通过一系列寄存器保证固件和OS可以得到足够的信息,有足够的手段控制EIST的工作模式。
C-State P-State是 ACPI 规范中的内容,ACPI全称 Advanced Configuration and Power Interface,是固件和OS的电源管理接口和模型。
ACPI规范定义了CPU的工作状态,包含
整个关系如下图:

C-state 有C0,C1…Cn多种模式,但只有 C0 是正常工作模式(active),其他方式都是idle状态,只是idle的程度不同,C后的数越高,CPU睡眠得越深,CPU的功耗被降低得越多,同时需要更多的时间回到C0模式。
在下表所列的模式中,C1 到 C3通过切断 CPU 内部的时钟,C4 到 C6 模式通过降低 CPU 的电压。”Enhanced”模式两种方式都采用。

EIST 各个工作频率是通过在C0下的各种P-states表现出来的。固件会检测 CPU 是否支持 EIST,如果不支持就没什么事了。
OS知道现在的工作量,由它来决定是不是要在各个P-states之间迁移。Linux的支持始于Linux 2.6,由cpufreq来提供支持。
Intel Turbo Boost 是Intel在系列处理器实现的技术,通过动态控制处理器的时钟率来激活处理器运行在超过基础操作主频。
Intel Turbo Boost 监控处理器当期使用情况,以及处理器是否接近最大热量设计功率(thermal design power, TDP)。
Turbo Boost允许一个或多个CPU核心运行在更高的P-states(turbo P-state),这个最大P-state需要考虑以下因素:
1) 激活的核心数量( C0状态)
2) 评估当前处理器消耗(Imax)
3) 评估处理器电能消耗(TDP - Thermal Design Power)
4) 处理器稳定
内核启动参数需要激活P-state驱动后才能使用Turbo Boost功能。不过,Intel仍然建议处理器工作在基础时钟速度(base clock speed),因为Intel不承诺处理器任何时候都能够达到最大Turbo Boost speed。
cpufreq 为在Linux 内核中更好的支持不同 CPU 的变频技术提供了一个统一的设计框架,cpufreq 在设计上主要分为以下三个模块:
1) cpufreq 模块(cpufreq module)对如何在底层控制各种不同 CPU 所支持的变频技术以及如何在上层根据系统负载动态选择合适的运行频率进行了封装和抽象,并在二者之间定义了清晰的接口,从而在设计上完成了前文所提到的对 mechanism 与 policy 的分离。
2) 在 cpufreq 模块的底层,各个 CPU 生产厂商只需根据其变频技术的硬件实现和使用方法提供与其 CPU 相关的变频驱动程序(CPU-specific drivers),例如 Intel 需要提供支持 Enhanced SpeedStep 技术的 CPU 驱动程序,而 AMD 则需要提供支持 PowerNow! 技术的 CPU 驱动程序。
3) 在 cpufreq 模块的上层,governor 作为选择合适的目标运行频率的决策者,根据一定的标准在适当的时刻选择出 CPU 适合的运行频率,并通过 cpufreq 模块定义的接口操作底层与 CPU 相关的变频驱动程序,将 CPU 设置运行在选定的运行频率上。目前最新的 Linux 内核中提供了 performance 、powersave 、userspace、conservative 和 ondemand 五种 governors 供用户选择使用,它们在选择 CPU 合适的运行频率时使用的是各自不同的标准并分别适用于不同的应用场景。用户在同一时间只能选择其中一个 governor 使用,但是可以在系统运行过程中根据应用需求的变化而切换使用另一个 governor 。
这种设计带来的好处是使得 governor 和 CPU 相关的变频驱动程序的开发可以相互独立进行,并在最大限度上实现代码重用,内核开发人员在编写和试验新的 governor 时不会再陷入到某款特定 CPU 的变频技术的硬件实现细节中去,而 CPU 生产厂商在向 Linux 内核中添加支持其特定的 CPU 变频技术的代码时只需提供一个相对来说简单了很多的驱动程序,而不必考虑在各种不同的应用场景中如何选择合适的运行频率这些复杂的问题。
CPU数据预读取功能,如果设置为Enabled,会预取流并发送到它的一级缓存,以改善数据处理和系统性能。
IP数据预读取功能。
几个概念:
ACPI - MADT 模式,用来设置操作系统是否可以对电源进行控制:
DDR 速度配置,内存运行频率。可以超频内存。在改变处理器的外频后,由于前端总线的频率也会改变,所以需要改变内存频率保证总线同步。
一些BIOS选项参考,不同设备显示也不同,单位为MHz:
CPU 是通过前端总线连接到北桥芯片,进而通过北桥芯片和内存、显卡交换数据。
前端总线是CPU和外界交换数据的最主要通道,因此前端总线的数据传输能力对计算机整体性能作用很大,如果没足够快的前端总线,再强的CPU也不能明显提高计算机整体速度。
数据传输最大带宽取决于所有同时传输的数据的宽度和传输频率,即数据带宽=(总线频率×数据位宽)÷8。
前端总线频率越大,代表着CPU与北桥芯片之间的数据传输能力越大,更能充分发挥出CPU的功能。
外频具体是指CPU到芯片组之间的总线速度。外频是CPU与主板之间同步运行的速度,而且目前的绝大部分电脑系统中外频,也是内存与主板之间的同步运行的速度,在这种方式下,可以理解为CPU的外频直接与内存相连通,实现两者间的同步运行状态。
由于CPU工作频率不断提高,而PC机的一些其他设备(如插卡、硬盘等)却受到工艺的限制,不能承受更高的频率,因此限制了CPU频率的进一步提高。
倍频技术就是使外部设备可以工作在一个较低频率(这个较低频率就是外频)上,而又不限制影响CPU本身的工作频率(主频),因为CPU主频就是外频的倍数。
前端总线与外频在以前的很长一段时间里(Pentium 4出现之前)是相同的。随着计算机技术的发展,人们发现前端总线频率需要高于外频,因此采用了QDR(Quad Date Rate)技术(4倍并发),或者其他类似的技术实现。
一般来说,主频和前端总线频率都是以外频为基数,前者是乘以倍频数,后者是乘以2/4/8,。
一般用三种频率来对内存进行描述——核心频率/时钟频率/数据传输速率。
对于DDR来说,三者的比例是1:1:2,对于DDR2来说,三者的比例关系是1:2:4。
设置内存温度调节模式,菜单选项为:
设置内存省电功能。

将 Clientset、dynamic.Interface 、ns和文件地址传入方法即可。如何创建 Clientset、dynamic.Interface ,可以参考我另一篇文章 《kubernetes 开发之 client-go 学习》。
import (
"errors"
"fmt"
"io"
"strconv"
"time"
"os"
"go/ast"
"go/token"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/restmapper"
)
func installYaml(clientSet *kubernetes.Clientset, dynamicClient dynamic.Interface, ns string, filename string) error {
f, err := os.Open(filename)
logrus.Info("=====================>" + filename)
if err != nil {
logrus.Error(err)
return err
}
d := yaml.NewYAMLOrJSONDecoder(f, 4096)
dc := clientSet.Discovery()
restMapperRes, err := restmapper.GetAPIGroupResources(dc)
if err != nil {
logrus.Error(err)
return err
}
restMapper := restmapper.NewDiscoveryRESTMapper(restMapperRes)
for {
ext := runtime.RawExtension{}
if err := d.Decode(&ext); err != nil {
if err == io.EOF {
break
}
logrus.Fatal(err)
}
// runtime.Object
obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(ext.Raw, nil, nil)
if err != nil {
logrus.Error(err)
return err
}
mapping, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
fmt.Printf("mapping:%+v\n", mapping)
if err != nil {
logrus.Error(err)
return err
}
// runtime.Object转换为unstructed
unstructuredObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
if err != nil {
logrus.Error(err)
return err
}
// fmt.Printf("unstructuredObj: %+v", unstructuredObj)
var unstruct unstructured.Unstructured
unstruct.Object = unstructuredObj
if ns == "" {
res, err := dynamicClient.Resource(mapping.Resource).Create(&unstruct, metav1.CreateOptions{})
if err != nil {
logrus.Error(err)
return err
}
GuessType(res)
} else {
res, err := dynamicClient.Resource(mapping.Resource).Namespace(ns).Create(&unstruct, metav1.CreateOptions{})
if err != nil {
logrus.Error(err)
return err
}
GuessType(res)
}
}
return nil
}
func GuessType(obj interface{}) {
fset := token.NewFileSet()
ast.Print(fset, obj)
}
pwd, _ := os.Getwd()
if pwd != "" {
pwd = pwd + "/"
}
err := installYaml(clientSet, dynamicClient, "", pwd+"abcdef.yaml")
if err != nil {
return err
}
与创建资源基本相同,不同的是我们传入 dynamic client 内的数据不是yaml信息,而是资源名,所以要从yaml文件中解析资源名。
func uninstallYaml(clientSet *kubernetes.Clientset, dynamicClient dynamic.Interface, ns string, filename string) error {
f, err := os.Open(filename)
if err != nil {
logrus.Error(err)
return err
}
d := yaml.NewYAMLOrJSONDecoder(f, 4096)
dc := clientSet.Discovery()
restMapperRes, err := restmapper.GetAPIGroupResources(dc)
if err != nil {
logrus.Error(err)
return err
}
restMapper := restmapper.NewDiscoveryRESTMapper(restMapperRes)
for {
ext := runtime.RawExtension{}
if err := d.Decode(&ext); err != nil {
if err == io.EOF {
break
}
logrus.Fatal(err)
}
// runtime.Object
obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(ext.Raw, nil, nil)
if err != nil {
logrus.Error(err)
return err
}
mapping, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
// fmt.Printf("mapping:%+v\n", mapping)
if err != nil {
logrus.Error(err)
return err
}
// runtime.Object转换为unstructed
unstructuredObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
if err != nil {
logrus.Error(err)
return err
}
// fmt.Printf("unstructuredObj: %+v", unstructuredObj)
var unstruct unstructured.Unstructured
unstruct.Object = unstructuredObj
tmpMetadata := unstructuredObj["metadata"].(map[string]interface{})
tmpName := tmpMetadata["name"].(string)
tmpKind := unstructuredObj["kind"].(string)
logrus.Info("deleting resource name: " + tmpName + ", kind: " + tmpKind + ", ns: " + ns)
if ns == "" {
err := dynamicClient.Resource(mapping.Resource).Delete(tmpName, &metav1.DeleteOptions{})
if err != nil {
logrus.Error(err)
return err
}
} else {
err := dynamicClient.Resource(mapping.Resource).Namespace(ns).Delete(tmpName, &metav1.DeleteOptions{})
if err != nil {
logrus.Error(err)
return err
}
}
}
return nil
}
uninstallYaml(clientSet, dynamicClient, "", "abcdef.yaml")

按时间查找可以使用参数:
find ./ -mtime 0 #返回最近24小时内修改过的文件。
find ./ -mtime 1 #返回的是前48~24小时修改过的文件,注意不是48小时以内修改过的文件。
find . -name '*.php' -mmin -30 #查找最近30分钟修改的当前目录下的.php文件
find . -name '*.inc' -mtime 0 -ls #查找最近24小时修改的当前目录下的.php文件,并列出详细信息