Qeuroal's Blog

静幽正治

Anaconda创建的虚拟环境多用户共享访问使用

在服务器上的sudo用户安装了anaconda,假设现在配置了虚拟的环境pytorch,需要怎么设置配置文件,才能保证连接服务器的别的标准用户(不具有sudo权限)怎么可以用到这个环境.

软件下载

建议使用国内源,例如清华大学开源软件镜像站。下载对应架构的安装包,例如 Anaconda3-2022.05-Linux-x86_64.sh。注意下载的是 anaconda3。下面假定你在 root 用户中执行指令,并且之前没有安装过 anaconda。

软件安装

  1. 运行下载的文件

    通过 chmod +x 为它增加执行权限

  2. 回车开始安装

  3. 阅读并输入 yes

  4. 指定安装目录,例如 /opt/anaconda3. (不要放在 root 根目录(~)下。)

  5. 等待安装完成

用户组与目录权限

为了使 anaconda 的文件仍归 root 所有,我们将新建一个用户组来为其余用户提供访问权限

1
2
3
4
5
6
groupadd condagroup # 新建一个名为 condagroup 的组;可以使用其它名称
adduser <username> condagroup # 将需要的用户加入该组
chgrp -R condagroup /opt/anaconda3 # 将安装目录转给该组
chmod 770 -R /opt/anaconda3 # 设置 root 用户与 condagroup 组的读写权限
find /opt/anaconda3 -type d -exec chmod g+s {} + # 设置组继承,使以后新建的文件夹仍属于 condagroup 组
chmod g-w /opt/anaconda3/envs # 共享环境只能由 root 修改

新环境位置

接下来,为了确保其余用户可以正确地在自己的目录中使用 -n <name> 新建环境,还要创建系统级的 anaconda 配置文件。在安装目录下(/opt/anaconda3)新建.condarc文件并写入

1
2
3
envs_dirs:
- /opt/anaconda3/envs
- ~/.conda/envs

根据 Conda configuration,envs_dirs是搜索命名环境的目录列表。创建新的命名环境时将放置在第一个可写位置,因此 root 用户将默认创建在安装目录下,成为共享环境,而其余用户会创建在自己的主目录中。

关于更多的管理选项,参见 Administering a multi-user conda installation。

你可能会想把这个文件的权限设为 644来避免被其余用户改动。这也是默认行为,因为 root 用户的默认 umask 是 0022。我们接下来将介绍这个 umask 可能带来的问题。

关于 umask

umask 控制新建文件的权限,简单来说是对指定的权限位进行排除。详细信息参见它的维基百科。

前述文件共享的机制是通过组读写权限完成的,意味着 anaconda 的文件需要有用户组的读与写权限。普通用户的默认 umask 是 0002,提供了用户组写仅限,但 root 用户的0022并没有。因此在使用 root 用户创建共享环境前需要修改 umask。

1
2
3
umask 0002
conda create -n env_name python # 示例
umask 0022 # 你可能会想恢复原值

否则会导致其它用户无权访问某些新下载的包的缓存等问题。在这种情况下,可以找到相应的文件并为其附加用户组写权限chmod g+w。

新增用户

现在你已经安装好了想要的 anaconda。如果有新用户,只需将其加入condagroup用户组,即可使用共享环境或创建新环境。

conda 环境配置

方法1: 局部(用户)配置 (Recommend)

以普通用户执行如下操作, 但是需要在所有的权限设置完毕之后方可使用

  1. 运行命令 eval "$(/opt/anaconda3/bin/conda shell.<YOUR_SHELL_NAME> hook)"

    如: eval "$(/opt/anaconda3/bin/conda shell.zsh hook)"

  2. 运行命令 conda initconda init <YOUR_SHELL_NAME>

    注: conda init 好像只会修改 .bashrc 文件

  3. 设置关闭自启动base环境

    1
    conda config --set auto_activate_base false

    或者修改文件 ~/.condarc

    1
    auto_activate_base: false

方法2: 全局(root)配置 (Not recommend)

以root用户进行如下操作

  1. 使用vim打开 /etc/profile, 在末尾添加

    1
    export PATH=/opt/anaconda3/bin:$PATH

    目的是为了让各用户的终端都能找到conda并运行。如果你安装在其它位置,请对应地更改目录值(下同)

  2. 运行 source /etc/profile 应用这项更改

方法3: 直接配置.bashrc或.zshrc

  1. vim ~/.bashrc

  2. 在最后一行添加:

    1
    export PATH="/opt/anaconda3/bin:$PATH"
  3. 用来激活环境变量

    1
    source ~/.bashrc
  4. 激活:

    • source activate
    • conda activate
  5. 退出激活:

    • source deactivate
    • conda deactivate

常见问题

Q: conda create 创建的目录不在 ~/.conda/envs

A: 删除 /opt/anaconda3/envs/.conda_envs_dir_test 文件

参考:

激活环境时设置环境变量

假设环境名为 env_name, 在env_name环境目录中, 创建文件夹 etc/conda/activate.d。在该文件夹下,创建 *.sh (linux/macos) 或 *.bat (windows) 文件, 将需设置的环境变量或脚本写入其中, 并通过 chmod +x *.sh 添加可执行权限. 当激活虚拟环境时, 该脚本自动运行.

分步骤如下:

  1. 在你的虚拟环境的 etc/conda/activate.d/ 目录下创建一个脚本文件

    1
    2
    3
    conda activate env_name
    mkdir -p $CONDA_PREFIX/etc/conda/activate.d
    touch $CONDA_PREFIX/etc/conda/activate.d/env_vars.sh
  2. 编辑env_vars.sh文件,添加你需要的环境变量:

    1
    2
    3
    4
    #!/bin/sh

    export MY_VAR="my_value"
    export ANOTHER_VAR="another_value"
  3. env_vars.sh 添加可执行权限:

    1
    chmod +x $CONDA_PREFIX/etc/conda/activate.d/env_vars.sh

QAs

  1. UnicodeEncodeError: ‘ascii’ codec can’t encode character ‘\xe4’ in position 89: ordinal not in range(128)

    • 原因: 字符编码问题

    • 解决方案:

      • 方法1: 临时生效

        1. 运行命令

          1
          2
          export LANG="en_US.UTF-8"
          export LC_ALL="en_US.UTF-8"
        2. 再执行你需要执行的命令即可

      • 方法2: 当前用户永久生效

        有时 Linux 系统中编码并不能统一使用,而是只针对某用户下才使用该编码,即当使用 FineBI 的时候,在该系统用户下才能使用该编码。因此编辑配置文件时需要在该用户下编辑。

        1. 打开 ~/.bash_profile

          1
          vim ~/.bash_profile
        2. 在最后一行后面追加:

          1
          2
          export LANG="en_US.UTF-8"
          export LC_ALL="en_US.UTF-8"
        3. 重启终端或运行 source ~/.bash_profile

        注:~/.bash_profile 是每个用户都可使用该文件输入专用于自己使用的 shell 信息。

      • 方法3: 系统级对所有用户永久有效

        对整个系统都有效的修改方式,使整个系统都适应于该系统编码。该方法是在系统配置文件中添加编码方式将默认的方式覆盖掉。执行的命令如下:

        1. 打开 profile

          1
          vim /etc/profile
        2. 打开文件后在最后一行后面追加:

          1
          2
          export LANG="en_US.UTF-8"
          export LC_ALL="en_US.UTF-8"
        3. 重启终端或运行 source /etc/profile

      • 方法4: 使用 locale-gen/etc/locale.conf

        当需要生成并设置系统的默认语言环境时使用。

        1. 编辑 /etc/locale.gen,去掉 en_US.UTF-8 UTF-8 以及 zh_CN.UTF-8 UTF-8 行前的注释符号(#):

          1
          vim /etc/locale.gen
        2. 然后使用如下命令生成 locale:

          1
          locale-gen
        3. /etc/locale.conf 输入内容:

          1
          echo 'LANG=en_US.UTF-8'  > /etc/locale.conf

重点

如果要改变变量的值就用指针,不改变就用变量本身;使用变量本身,那么相当于读取,对原来的数据没有任何影响。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <iostream>

using namespace std;

typedef struct Node {
int data;
struct Node *next;
}Node;

typedef struct Node *LinkList;

void initLinkList(LinkList *L)
{
(*L) = new Node;
(*L)->data = 0;
(*L)->next = NULL;
}

bool insertLinkList(LinkList head, int pos, int value)
{
LinkList p = head, t;
int j = 1;

while (p && j < pos) {
p = p->next;
j++;
}

if (!(p) || j > pos) return false;

t = new Node;
t->data = value;
t->next = p->next;
p->next = t;
head->data++;

return true;
}


bool deleteLinkList(LinkList l, int pos, int *value)
{
LinkList p = l, q;
int j = 1;

while (p->next && j < pos) {
p = p->next;
j++;
}

if (!(p->next) || j > pos) return false;

q = p->next;
p->next = q->next;
delete(q);
l->data--;
return true;
}

void clearLinkList(LinkList l)
{
LinkList p = l->next, q;
l->next = NULL;
while (p) {
q = p->next;
delete (p);
p = q;
l->data--;
}
}

void showLinkList(LinkList l)
{
cout << "Length is " << l->data << endl;
l = l->next;
while (l) {
cout << l->data << "\t";
l = l->next;
}
cout << endl;

return ;
}

int main()
{
LinkList head = NULL;
initLinkList(&head);

int value_del;
deleteLinkList(head, 1, &value_del);

for (int i = 1; i <= 10; i++) {
insertLinkList(head, i, i);
}
insertLinkList(head, 4, 10);
showLinkList(head);

deleteLinkList(head, 4, &value_del);
showLinkList(head);

clearLinkList(head);
showLinkList(head);

return 0;
}

详解

  1. 该链表是有头结点的链表;
  2. 什么时候用 LinkList LLinkList *L
    1. 需要改变指针的值的时候用 LinkList *L,若对指针的值没有改变时,使用 LinkList L
  3. 链表注意事项:
    1. LinkList head;只是定义了一个 变量名为head的指针变量,是一个野指针,那么需要在定义的时候进行初始化,即:LinkList head = NULL
    2. 想要使用 head 指向头结点,需要自己 new 一个结构体,将这个结构体的地址赋给 head
  4. insertLinkListdeleteLinkList的异同:
    1. insertLinkListdeleteLinkList不论在位置 pos 处插入一个结点还是在pos处删除结点,都是对 pos-1 进行操作。
    2. 在使用 while 循环时,insertLinkList是以第j个位置为判断对象,而 deleteLinkList是以第j+1个位置为判断对象的(其中:头结点为第1个位置)。

字体下载

推荐使用 JetBrainsMono Nerd Font

网站

Nerd Fonts

单独字体

  • JetBrainsMono Nerd Font 下载方式(3选1):

  • Hack Nerd Font Github

  • Caskaydia Cove Nerd Font Github

  • MesloLGS NF Github(官网)

    1
    2
    3
    4
    5
    mkdir fonts
    curl -o ./fonts/MesloLGS\ NF\ Regular.ttf https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/MesloLGS%20NF%20Regular.ttf
    curl -o ./fonts/MesloLGS\ NF\ Bold.ttf https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/MesloLGS%20NF%20Bold.ttf
    curl -o ./fonts/MesloLGS\ NF\ Italic.ttf https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/MesloLGS%20NF%20Italic.ttf
    curl -o ./fonts/MesloLGS\ NF\ Bold\ Italic.ttf https://raw.githubusercontent.com/romkatv/powerlevel10k-media/master/MesloLGS%20NF%20Bold%20Italic.ttf

Ubuntu安装win10字体

  1. 进入windows : /media/qeuro/系统/Windows/Fonts

  2. sudo cp *.ttf ~/桌面/WinFonts

  3. sudo cp *.TTF ~/桌面/WinFonts

  4. cd ~/桌面

  5. sudo mv WinFonts /usr/share/fonts/

  6. sudo chmod -R 755 /usr/share/fonts/WinFonts

  7. sudo mkfontscale && sudo mkfontdir && sudo fc-cache -fv

  8. 字体名称对照:

    ttf 字体
    arial.ttf Arial
    couri.ttf Courier New
    times.ttf Times New Roman
    timesbd.ttf Times New Roman Bole
    FZSTK.TTF 方正舒体
    FZYTK.TTF 方正姚体
    msyh.ttf 微软雅黑
    msyhbd.ttf 微软雅黑Bold
    simfang.ttf 仿宋GB_2312
    simhei.ttf 黑体
    simkai.ttf 楷体GB_2312
    SIMLI.TTF 隶书
    simsun.ttc 宋体、宋体PUA、新宋体
    SIMYOU.TTF 幼圆
    STCAIYUN.TTF 华文彩云
    STFANGSO.TTF 华文仿宋
    STHUPO.TTF 华文琥珀
    STKAITI.TTF 华文楷体
    STLITI.TTF 华文隶书
    STSONG.TTF 华文宋体
    STXIHEI.TTF 华文细黑
    STXINGKA.TTF 华文行楷
    STXINWEI.TTF 华文新魏
    STZHONGS.TTF 华文中宋
    SURSONG.TTF 宋体-方正超大字符集

  1. Cupertino:图标 —— icons

  2. dash-to-dock-gnome:dash to dock

  3. grub2-themes-master:grub启动界面 —— sudo ./install.sh -v

  4. High_Ubunterra_CC : Ubuntu 锁屏启动界面(模糊的那个)

  5. Mojave-light: 主题 —— themes

  6. suadesplas: 启动动画

  7. 美化网址有去除启动时紫框的说明是:https://www.cnblogs.com/feipeng8848/p/8970556.html

    即:找到/boot/grub/grub.cfg文件,找到这样一行: if background_color 44,0,30,0;修改成 if background_color 0,0,0,0;就会去除grub在选中Ubuntu系统之后出现的短暂的紫色。

  8. 美化网址:

    1. https://www.cnblogs.com/feipeng8848/p/8970556.html
    2. https://blog.csdn.net/weixin_40389121/article/details/81703577
    3. https://www.cnblogs.com/lishanlei/p/9090404.html

清理

  • sudo apt-get purge -y --auto-remove

  1. grub启动界面:直接使用 sudo ./install.sh -v,而不是sudo ./install.sh -v -2
  2. 安装微软字体库时,使用Tab健选择确定
  3. 搜狗输入法 如果调到第一门语言就会乱码(可能有的电脑没问题)
  4. 安装好anaconda后是没有图标的
  5. 安装anaocnda直接 bash anaconda.sh
  6. 安装anaconda之前应该先安装 Vscode

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from mpl_toolkits.mplot3d import Axes3D

# 解决中文乱码问题
# myfont = fm.FontProperties(fname='/home/zk/study/python_lessions/DataVisualiztion/Library/Fonts/simsun.ttc', size=14
myfont = 'kaiti'
matplotlib.rcParams["axes.unicode_minus"] = False

def simple_plot():
"""
simple plot
:return:
"""
#生成画布
plt.figure(figsize=(8,6), dpi=80)

#打开交互模式
plt.ion()

# 循环
for index in range(100):
#清除原有图像
plt.cla()
#设定标题等
plt.title("动态曲线图",fontproperties=myfont)
plt.grid(True)

#生成测试数据
x = np.linspace(-np.pi + index, np.pi+0.1*index, 256,endpoint=True)

y_cos, y_sin = np.cos(x),np.sin(x)

# 设置x轴
plt.xlabel("x轴", fontproperties= myfont)
plt.xlim(-4 + 0.1*index,4 + 0.1*index)
plt.xticks(np.linspace(-4 + 0.1 * index, 4 + 0.1 * index, 9, endpoint=True))
# 设置Y轴
plt.ylabel("Y轴", fontproperties=myfont)
plt.ylim(-1.0, 1.0)
plt.yticks(np.linspace(-1, 1, 9, endpoint=True))

# 画两条曲线
plt.plot(x, y_cos, "b--", linewidth=2.0, label="cos示例")
plt.plot(x, y_sin, "g-", linewidth=2.0, label="sin示例")


# 设置图例位置,loc可以为[upper, lower, left, right, center]
plt.legend(loc="upper left", prop={'family': "kaiti"}, shadow=True)

# 暂停
plt.pause(0.1)

# 关闭交互模式
plt.ioff()

# 图形显示
plt.show()
return


if __name__ == '__main__':
simple_plot()

注意:

  1. 如果没有交互模式 那么就不能动态绘图
  2. plt.figure是可以自己显示画板的

全部命令

1
2
3
4
5
6
ubuntu-drivers devices
sudo apt install nvidia-440
sudo apt install nvidia-driver-440
reboot
lshw -numeric -C display
lspci -vnn | grep VGA

具体步骤

方法一

  1. 禁用显卡的方法这里在记一下:在/etc/modprobe.d/blacklist.conf里添加,如下内容,并执行 sudo update-initramfs -u,

    1
    2
    blacklist nouveau
    options nouveau modeset=0
  2. 重启后用lsmod | grep nouveau,如果没有任何输出说明禁用成功。

    但是我并没有禁用显卡

  3. 直接输入: sudo ubuntu-drivers autoinstall

  4. 验证是否安装成功:nvidia-smi

方法二 (推荐)

  1. 如果需要安装新版本的驱动可以先添加源:
    1
    2
    sudo add-apt-repository ppa:graphics-drivers/ppa
    sudo apt update
  2. 执行 ubuntu-drivers devices,如下所示:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    == /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0 ==
    modalias : pci:v000010DEd00001C8Csv00001028sd00000798bc03sc00i00
    vendor : NVIDIA Corporation
    model : GP107M [GeForce GTX 1050 Ti Mobile]
    driver : nvidia-driver-390 - third-party free
    driver : nvidia-driver-430 - distro non-free
    driver : nvidia-driver-415 - third-party free
    driver : nvidia-driver-435 - distro non-free
    driver : nvidia-driver-440 - third-party free recommended
    driver : nvidia-driver-410 - third-party free
    driver : xserver-xorg-video-nouveau - distro free builtin
  3. 选择 recommended (推荐的) 安装: sudo apt install nvidia-driver-440
  4. 可使用下面命令,查看是否安装成功
    1
    2
    lshw -numeric -C display
    lspci -vnn | grep VGA
    显示结果:
    1. lshw -numeric -C display
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      WARNING: you should run this program as super-user.
      *-display
      description: VGA compatible controller
      product: GP107M [GeForce GTX 1050 Ti Mobile] [10DE:1C8C]
      vendor: NVIDIA Corporation [10DE]
      physical id: 0
      bus info: pci@0000:01:00.0
      version: a1
      width: 64 bits
      clock: 33MHz
      capabilities: vga_controller bus_master cap_list rom
      configuration: driver=nvidia latency=0
      resources: irq:128 memory:de000000-deffffff memory:c0000000-cfffffff memory:d0000000-d1ffffff ioport:e000(size=128) memory:df000000-df07ffff
      *-display
      description: VGA compatible controller
      product: Intel Corporation [8086:591B]
      vendor: Intel Corporation [8086]
      physical id: 2
      bus info: pci@0000:00:02.0
      version: 04
      width: 64 bits
      clock: 33MHz
      capabilities: vga_controller bus_master cap_list rom
      configuration: driver=i915 latency=0
      resources: irq:127 memory:dd000000-ddffffff memory:b0000000-bfffffff ioport:f000(size=64) memory:c0000-dffff
      WARNING: output may be incomplete or inaccurate, you should run this program as super-user.
    2. lspci -vnn | grep VGA
      1
      2
      00:02.0 VGA compatible controller [0300]: Intel Corporation Device [8086:591b] (rev 04) (prog-if 00 [VGA controller])
      01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP107M [GeForce GTX 1050 Ti Mobile] [10de:1c8c] (rev a1) (prog-if 00 [VGA controller])

参考网址

win10

  1. 下载地址:https://www.oracle.com/java/technologies/javase-downloads.html

  2. 选择 Java SE 8 - Oracle JDK - JDK Download

  3. 双击打开jdk,如: jdk-8u202-windows-x64.exe

  4. 安装完JDK后配置环境变量。右击“计算机”。点击“属性”

  5. 点击“高级系统设置”

  6. 点击“高级”,再点击“环境变量”。

  7. 点击“新建”。变量名输入JAVA_HOME,变量值输入安装路径。D:\Java\jdk1.8.0_202\

  8. 点击“新建”。变量名输入 CLASSPATH ,变量值输入 .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar

    注意前面有一个 . 千万不要忘了。

  9. 在系统变量中找到“Path”,点击“编辑”

    • (Error): 变量值输入%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin; (这个是不行的,javac 用不了)
    • (Success): D:\Java\jdk1.8.0_202\bin;D:\Java\jdk1.8.0_202\bin\jre\bin; (分不分开都可以,只要是绝对路径即可,并且在前在后应该无关,如果 javac 用不了,那么就把这两个移到最前端即可)

macOS

下载

Java Downloads | Oracle

安装JDK1.8

下载的安装包jdk-8u281-macosx-x64.dmg、双击pkg,按提示流程安装:

确定jdk安装完整

按照完成以后、我们可以查看JDK的安装路径、在资源库/Library下面会出现一个Java的文件夹、目录层级如下:/Library/Java/JavaVirtualMachines/jdk1.8.0_281.jdk

  1. 打开终端

  2. 如果想要配置 jdk,那么我们需要知道 jdk 的安装目录,与 WIN 系统有很大的不同,我们在 MAC 中想要查看 jdk 的安装路径需要在终端执行以下的命令行:

    1
    /usr/libexec/java_home -V

    如图所示:带有 ==Java SE 8== 和 ==jdk1.8.jdk== 的这一行信息是最重要的,可以将这段信息复制下来,后面需要使用!

  3. 查看 Java 版本:java -version

配置JDK的系统环境变量

在配置环境变量之前,我本人遇到一种情况就是:安装了jdk安装包之后,就可以直接在终端里面使用java -version 和java以及javac的命令。也就是说不需要配置jdk的环境变量也可以直接使用。后面我查了一些资料,我本人的理解是:在MAC系统中,jdk会默认安装到“用户”的目录下,当我们打开终端的时候会直接扫描用户,所以可以直接执行上面的三个命令。

但是无论是否可以直接使用java命令,我个人都建议配置jdk,具体的流程如下:

  1. vim ~/.zshrc 在末尾添加如下代码:

    1
    2
    3
    export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
    export CLASSpATH=${JAVA_HOME}/lib
    export PATH=${JAVA_HOME}/bin:${PATH}

    注意:java_HOME=后面填入的信息就是“之前我们复制的那段重要信息”(即jdk的安装目录),其余的配置信息不变与我相同就可以。(一定要注意保存文件)

  2. source ~/.zshrc

  3. 在终端输入 echo $JAVA_HOME,如果配置成功则会显示刚刚配置的 JAVA_HOME 路径信息。(echo后面有空格),也可以直接使用 vim ~/.zshrc 来查看环境变量的信息。如图:

  4. 查看java版本:java -version

  5. javac的命令来检验是否配置成功

    Note:系统会输出 javac 的帮助信息。如果成功,说明已经成功配置了JDK , 否则需要仔细检查上面的步骤的配置是否正确。

jdk 文档

jdk8

点击 Java 文档页面的“Tree”按钮,页面会显示 Java 中所有的类供你查询

0%