Centos ssh免密码登陆配置

测试 ssh 是否安装

1
rpm -qa | grep ssh

若返回的结果中包括 SSH client 和 SSH server ,则不需要再安装 若需安装,通过以下命令

1
2
yum install openssh-clients 
yum install openssh-server

查看主机名称

1
hostname

然后

1
ssh hostname(自己的主机名)

设置免密码登陆

1
2
cd ~/.ssh 
ssh-keygen -t rsa

通过 ssh-keygen 命令来生成密钥对在.ssh 目录下(会有提示,回车即可)。
此命令执行后,会在~/.ssh 目录下生成私钥 id_rsa 和公钥 id_rsa.pub

1
cat id_rsa.pub >> authorized_keys 

将 id_rsa.pub 中的公钥信息保存到 authorized_keys 中

1
chmod 600 ./authorized_keys

修改文件授权 此时用 ssh hostname 命令,无需密码即可直接登陆。

大数据笔记索引

  • 虚拟机安装centos
  • centos8安装java的jdk
  • Centos ssh免密码登陆配置
  • centos8安装visual studio code
  • centos8 java 配置maven
  • centos8 配置 mysql 8.0
  • centos8 配置 sqlserver
  • centos8 配置 hadoop
  • centos8 配置 hbase
  • centos8 配置 spark
  • centos8 配置 flume
  • centos8 配置 kafka
  • Spark SQL
  • Spark Streaming基础
  • Spark Streaming进阶
  • Spark程序设计
  • OLAP引擎Impala
  • OLAP引擎Clickhouse
  • OLAP引擎Presto
  • 分布式数据仓库Hive基础
  • 分布式计算引擎MapReduce与资源管理YARN
  • 分布式NoSQL存储HBase
  • 分布式消息队列Kafka
  • Flink框架介绍
  • Tableau基础知识
  • 统计分析理论
  • 机器学习基础
  • 监督学习
  • 无监督学习
  • 人工智能

centos 配置visualstudio code

Visual Studio Code 安装

导入Microsoft GPG key:

1
sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc

官网下载vscode

1
sudo gedit /etc/yum.repos.d/vscode.repo

将下面的内容粘贴进去,并且启用 VS Code 源:

1
2
3
4
5
6
[code]
name=Visual Studio Code
baseurl=https://packages.microsoft.com/yumrepos/vscode
enabled=1
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc

保存文件,并且关闭你的文本编辑器。

安装最新版本的 Visual Studio Code,输入:

1
sudo dnf install code

升级visualstudio code

当一个新版本发布时,你可以通过你的桌面软件升级工具或者通过在终端运行下面的命令,来升级 Visual Studio Code:

1
sudo dnf update

.net core 安装

注册 Microsoft 密钥和源

1
sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm

依次执行安装SDK和运行时。

1
2
3
sudo yum install dotnet-sdk-3.1
sudo yum install dotnet-runtime-3.1
sudo yum install aspnetcore-runtime-3.1

打开扩展页面,搜索C#,安装C#支持;

打开sln文件所在文件夹,配置好launch.json文件,然后ctrl+f5就可以进行调试了。

第一个python手写识别程序

我的第一个AI应用是参考实战:从0搭建完整 AI 开发环境写出第一个 AI 应用AI应用开发实战 - 从零开始配置环境两篇文章进行的实施,故以该文做出相应的补充。

遇到的问题

‘python’ 不是内部或外部变量

命令行执行python –version提示’python’ 不是内部或外部变量,在命令行中输入

1
set PATH="C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64";%PATH%

之后,再输入

1
python --version

输出版本为3.6.5
但是关闭命令行之后,再输入python –version时,依旧提示 ‘python’ 不是内部或外部变量
故在计算机→属性右键→高级系统设置→环境变量→选择PATH→点击新建→将C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64添加→确定,之后再运行python –version,显示正常。

saved_model.pb路径不对

单独参考第一篇文章进行配置时,发现没有samples-for-ai\export\saved_model.pb这个路径。
原因是没有启动examples\tensorflow\TensorflowExamples.sln这个解决方案,将MNIST项目设置为启动项目并运行,则会有samples-for-ai\export\saved_model.pb这个文件了。

命令行无响应

安装scipy-1.1.0mxnet_cu90-1.2.0时,命令行一直无响应,解决方案是到scipy-1.1.0mxnet-cu90 1.2.0下载指定的文件,然后通过pip3命令来执行安装,其余问题也可以通过类似命令来解决。

1
2
pip3 install D:\scipy-1.1.0-cp36-none-win_amd64.whl
pip3 install D:\mxnet_cu90-1.2.0-py2.py3-none-win_amd64.whl

通过下载的文件可以得知,文件较大,命令行无法及时完成下载,所以需要有一定的耐心等待

注意需要将C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\Scripts添加到PATH变量中。

cudnn版本不对

现在官网https://developer.nvidia.com/cudnn提供的cudnn版本是7.4.1,而微软示例代码中的cudnn版本是7.0.3,高版本的cudnn也会导致编译失败,需要找低版本的7.0.的cudnn替换到*C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin\cudnn64_7.dll

运行结果

解决了这部分问题之后,能正常展示winform界面,运行结果如下:
正确识别
错误识别
该部分涉及到训练模型是否足够多的问题,该文不做深入的研究。

总结

参考资料中提及的两篇文章都已经是做手写识别非常好的入门资料,该文仅仅是对这两篇文章做一个相应的补充,以作备忘。
另外我希望早日掌握以下技能

识别开心消消乐的游戏界面,然后通过能够确定执行的最佳下一步,达到这个目的,我觉得我对人工智能的了解和我的AI编程就进入了新的层次了。

#参考资料

重构技巧之添加参数

最近在经手一个Winform项目,里面有个需求:TreeView控件选择不同的TreeNode时,需要展示不同的右键菜单。记录一下重构过程。

需求

现将公司内部需求初始需求转换如下:
如果TreeView选中的TreeNode是国家,则右键菜单展示”添加省”,一个选项。
如果TreeView选中的TreeNode是省份,则右键菜单展示”添加市”,”删除”两个选项。
如果TreeView选中的TreeNode是城市,则右键菜单展示”添加区”,”删除”两个选项。
如果TreeView选中的TreeNode是区,则右键菜单展示,”删除”一个选项。
这部分的伪代码如下:

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
var area = TreeView.SelectedNode.Tag as Area; //
if(area!=null)
{
var areaType=area.type;
ContextMenuStrip menuStrip = new ContextMenuStrip();
if(areaType==AreaType.国家)
{
menuStrip.Items.Add(new ToolStripMenuItem("添加省"));
}
if(areaType==AreaType.省份)
{
menuStrip.Items.Add(new ToolStripMenuItem("添加市"));
menuStrip.Items.Add(new ToolStripMenuItem("删除"));
}
if(areaType==AreaType.城市)
{
menuStrip.Items.Add(new ToolStripMenuItem("添加区"));
menuStrip.Items.Add(new ToolStripMenuItem("删除"));
}
if(areaType==AreaType.区)
{
menuStrip.Items.Add(new ToolStripMenuItem("删除"));
}

menuStrip.Show(e.Location);
}

后来业务发展了,除了AreaType.国家这个选项,右键菜单都需要添加一个”打开地图”的右键菜单,且位于右键菜单的最上方。
重构之后的示例代码变成了如下:

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
var area = TreeView.SelectedNode.Tag as Area; //
if(area!=null)
{
var areaType=area.type;
ContextMenuStrip menuStrip = new ContextMenuStrip();
if(areaType==AreaType.国家)
{
menuStrip.Items.Add(new ToolStripMenuItem("添加省"));
}
if(areaType==AreaType.省份)
{
menuStrip.Items.Add(new ToolStripMenuItem("打开地图"));
menuStrip.Items.Add(new ToolStripMenuItem("添加市"));
menuStrip.Items.Add(new ToolStripMenuItem("删除"));
}
if(areaType==AreaType.城市)
{
menuStrip.Items.Add(new ToolStripMenuItem("打开地图"));
menuStrip.Items.Add(new ToolStripMenuItem("添加区"));
menuStrip.Items.Add(new ToolStripMenuItem("删除"));

}
if(areaType==AreaType.区)
{
menuStrip.Items.Add(new ToolStripMenuItem("打开地图"));
menuStrip.Items.Add(new ToolStripMenuItem("删除"));
}

menuStrip.Show(e.Location);
}

这次需求变动,已经让我闻到了代码中的坏味道。增删改一个右键菜单需要修改好几处地方,删除右键菜单也是同理。
故需要对代码进行重构。

重构

提取函数,伪代码如下

1
2
3
4
5
6
7
8
private ContextMenuStrip menuStrip = new ContextMenuStrip(); //菜单转为私有属性
private void AddToolStripMenuItem(string controlName, bool isAdd)
{
if (isAdd)
{
this.menuStrip.Items.Add(new ToolStripMenuItem(controlName););
}
}

故调用处的实现代码变成了如下

1
2
3
4
5
6
7
8
9
10
11
12
var area = TreeView.SelectedNode.Tag as Area; //
if(area!=null)
{
var areaType=area.type;
this.menuStrip.Items.Clear();
AddToolStripMenuItem("添加省",areaType==AreaType.国家);
AddToolStripMenuItem("打开地图",!areaType==AreaType.国家);
AddToolStripMenuItem("添加市",areaType==AreaType.省份);
AddToolStripMenuItem("添加区",areaType==AreaType.城市);
AddToolStripMenuItem("删除",!areaType==AreaType.国家);
menuStrip.Show(e.Location);
}

若以后需求变更,打开地图需要改成打开百度地图,然后新增打开高德地图也只需要修改一行代码,并新增一行代码即可。

总结

该重构过程运用的是提取函数和函数添加参数。
AddToolStripMenuItem函数只关心菜单项是否添加,而不关心菜单项添加的逻辑是什么。
重构之后,右键菜单的可能的菜单项也一目了然,每一个菜单项对应的添加条件也一目了然。若isAdd参数对应的表达式过长,则可以将该表达式封装成函数进行传递。
通过该重构提高了项目的可维护性,也算是一种成就。

委托在重构中的运用

最近在工作中的一次重构过程中运用到了委托,记录一下。

场景

有一段示例代码如下

1
2
3
4
5
6
7
8
9
10
11
12
public class ProjectAClass
{
public static void CallMethod(bool isTrue)
{
if (isTrue)
{
ProjectB_StaticClass.DoSomething();
}
}

}

需求

后来因为业务的不断发展,需要把ProjectB从整个解决方案中移除掉。
ProjectB_StaticClassB.DoSomething();需要替换成 ProjectC_StaticClassC.DoSomething();
但是项目ProjectC需要引用ProjectA,故不能直接进行引用,否则会造成项目之间的循环依赖。

解决方案

ProjectAClass添加一个委托事件,CallMethod函数添加一个Dosometing dosometing的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ProjectAClass
{
public delegate void Dosometing();

public static void CallMethod(bool isTrue, Dosometing dosometing)
{
if (isTrue)
{
dosometing?.Invoke();
}
}
}

具体的调用代码处就变成了

1
ProjectAClass.CallMethod(true,()=>{ProjectC_StaticClassC.DoSomething();});

扩展

若ProjectAClass.CallMethod方法多地方出现,然而没有办法一下修改到位。可以通过参数默认值的方式来实现修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void CallMethod(bool isTrue, Dosometing dosometing=null)
{
if (isTrue)
{
if(dosometing == null)
{
ProjectB_StaticClass.DoSomething();
}
else
{
dosometing.Invoke(); // or dosometing()
}
}
}

该方法可以避免原来的调用方法进行大面积的修改。

总结

重构之后的代码ProjectAClass只需要判断条件是否满足,满足则dosometing,而不需要知道dosometing这个委托方法中具体细节。

用Dictionary替换switch case的注意事项

最近试图重构一段现做现卖的祖传代码,结果改完之后,性能急速下降,下面给出示意代码的截图,以便提醒自己工作需要更加认真和细心。

示例代码

错误的重构

差异对比
Dictionary的执行时间竟然是Switch case的四倍以上?原因是啥?我们来看一下各个动物的构造函数
构造函数
即生成Dictionary的每一个键值对的值的时候,都实例化了一个Animal的子类,每个子类的实例化都等待了十秒钟,总实例化就耗费了40秒钟。

正确的重构

正确重构
先获取对象的type,然后通过Activator.CreateInstance(type)创建对象。

总结

switch case转换成dictionary算得上是一种重构,起到了减少代码量,提高可维护性的效果。
这次我的失误也算是明白了一个深刻的道理,所有的重构需要建立在完整的测试机制的前提下,否则可能会造成严重的损失。
最后一句箴言如无必要,勿动祖传代码