之前自己手动和使用ubuntu自带的附加驱动安装,每次都失败,然后只能进bash删除重新安装。我记得之前启动时有错误提示。
现在就没想通过自带的安装了。今天手动安装完,启动直接卡死,通过搜索有篇文章说的,需要bios改为使用独立显卡。
然后我就才知道Discrete Graphics 为独立网卡,graphics device为集成显卡。进过很多次bios看到过,但是我认为的正好相反。
改完之后然后就正常启动,感觉图片色彩好像都更鲜艳了。流畅度到没有太大区别。
Read more...
Archive for linux
centos7编译升级内核到4.19
因为用到xdp相关的东西,centos7操作系统的内核版本为3.10,准备编译升级一下。还从来没有手动编译安装过。
看了官方文档,没有啥特别流程,讲了一些注意事项。我按照网上的步骤来的。
下载内核: curl -O https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.230.tar.xz
解压: tar xf linux-4.19.230.tar.xz
然后,把之前内核编译配置复制过来: cd linux-4.19.230 && make mrproper, cp /boot/config-3.10.0-1160.53.1.el7.x86_64 ../.config
进行配置:make menuconfig,看文档应该是make oldconfig,可能用这个读的.config文件吧。
配置没太敢改,只改了Processor type and features —> Processor family (Core 2/newer Xeon) 选了newer Xeon。这个我还翘"?"看了一下介绍,可以cat /proc/cpuinfo,看看cpu family, 6为new,15为old。
编译: make -j 32
安装:make modules_install && make install
配置启动:
查看当前启动选择:grub2-editenv list
设置默认第一个启动:grub2-set-default 0
确认设置:grub2-editenv list,这里我在/boot/目录下找了一下grub.cfg配置,第一行确实是刚安装的内核版本。
重启:reboot
重启没有什么问题,安全起来了。
还有几个编译依赖文件,之前我对照官方文档检查了几个主要的,但是有些需要devel版本的,起始发现没装还是得重新安装。
yum install ncurses-devel.x86_64 elfutils-libelf-devel openssl-devel
没啥难度,毕竟也算世界上最大的开源项目了吧,应该做的很容易。最难的是内核定制,完全不知道应该怎么选择,选择哪些配置能提升性能,不然本地编译的还比不上版本分发带的普适版本的性能好。
Read more...
ubuntu系统从18.04升级到20.04了
今天折腾了一天的ubuntu系统,先是18.04对于为这个电脑好多硬件不支持,声音,GPU都不行。决定升级20.04,20.04支持硬件驱动,但是从18.04到20.04升级太曲折了,升级完系统,wifi和声音都有问题,导致进不了系统,刚开始为切换到shell,禁止加载mod也是不行。
最后竟然发现进入恢复模式后,再切换到正常启动就能进入桌面了。恢复模式也提示了,桌面环境有的可能需要正常启动才能使用。为这个可能没正常启动,导致一些检测跳过了吧。后来装显卡驱动,升级了内核版本,然后突然间就好了。不知道为啥升级系统的版本的时候不给我直接升级内核版本。
哦对,不正常启动的时候,竟然cpu不太高,风扇呼呼转,不知道咋回事。正常了后也正常了。日志里的报错也没啥用,直到是wifi和声音mod的问题,但是没办法解决。
正常后的20.04的界面还挺好用,很流畅,也比之前好看多了。
开始界面调整外观风格没有变化,后来发现需要升级一下桌面,apt install ubuntu-desktop就可以了。
sudo lspci | grep -i nvidia
这个命令查看显卡信息的时候,因为没有显示,网上找了一个网站能通过id查询。
http://pci-ids.ucw.cz/mods/PC/10de?action=help?help=pci
url里的id是供应商id
再后来,帖子看多了,发现可以直接升级本地pci数据库。看来这电脑还真是硬件配置新啊。
sudo update-pciids
显卡驱动最后也没安装成功,懒得折腾了,暂时也用不到显卡的特殊功能,先这样吧。
Read more...
centos上搭建redmine,使用thin,nginx搭建
最近公司在找项目管理的软件,调研了一上午,然后给了几个方案。
一个是是否花钱,市面上的大部分都是花钱
第二个是是否本地部署,现在大部分不能本地部署,支持部署的也是花钱
之前用禅道,不支持多级子任务,不再使用,所以方案必须支持这点。
第三个是否能用破解版。
然后可以用破解版,我首先部署了jira,最后发现也不支持,插件好像也不行,官网也有人说了好几年了。
最后只能上redmine,这个系统勾起了我遥远的回忆,好像正式工作第一家就是用的这个系统,那时候我还改过ruby代码。这个我通过一个演示系统提前知道能多级。
下午又把这个redmine给部署了。这里简单总结一下,不是最优方案,但是内部使用基本没大问题。
使用的方案是,thin+nignx。thin类似于python中uwsgi等的那些。下边的方法是回忆着来的,不一定全,先记一波,以后部署再补充。
redmin安装查看官网教程足够。
安装完有测试启动方式bundle exec rails server webrick -e production,这个肯定不能用在正式环境,可能单线程,没验证
ruby的安装使用的rvm,类似Python里pyenv。
thin安装
gem install thin
thin install 能安装开机启动脚本,和etc下的目录。/etc/rc.d/thin
thin命令能生成配置文件,我直接复制的网上改的
cat /etc/thin/redmine.yml
pid: tmp/pids/thin.pid
wait: 30
timeout: 30
log: log/thin.log
max_conns: 1024
require: []
environment: production
max_persistent_conns: 512
servers: 4
daemonize: true
user: redmine
#socket: /tmp/thin.sock
address: 0.0.0.0
port: 8080
chdir: /data/redmine-4.1
这个配置刚开始怎么试sock都不行,后来端口也不行,我查了一下发现是selinux没关闭,关闭后再没试。让他们先通过thin起一个端口去验证了。
/etc/rc.d/thin start
/etc/rc.d/thin stop
这里会有问题
/usr/local/rvm/gems/ruby-2.6.6/gems/activesupport-5.2.4.5/lib/active_support/dependencies.rb:291:in `require': cannot load such file -- thin/connection (LoadError)
查了一下发现得在Gemfile文件里加上thin的引用,没写过ruby,看不懂,添加 gem "thin" 后 启动正常
nginx配置
这里配置基本复制的网上的,静态文件还是用的thin的,没走nginx,因为懒得去修改静态文件目录的权限了。
/etc/nginx/conf.d/redmine.conf
upstream thin_cluster {
# server unix:/tmp/thin.0.sock;
# server unix:/tmp/thin.1.sock;
# server unix:/tmp/thin.2.sock;
# server unix:/tmp/thin.3.sock;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
server 127.0.0.1:8083;
}
server {
listen 10.10.12.240:3000;
server_name 10.10.12.240;
access_log /var/log/nginx/redmine-proxy-access;
error_log /var/log/nginx/redmine-proxy-error;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 100m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
# root /data/redmine-4.1/public;
proxy_redirect off;
location / {
# try_files $uri/index.html $uri.html $uri @cluster;
try_files $uri.html $uri @cluster;
}
location @cluster {
proxy_pass http://thin_cluster;
}
}
Read more...
texlive在ubuntu上的安装
准备玩点高级一点的东西了,xelatex看着不错,搜了一番,感觉texlive比较不错。也下载了Texmacs,那个只支持原生的latex,xelatex的导入导出不支持。现在已经懒得折腾东西,但是想想还是折腾折腾吧。直接apt安装的版本是2017的,感觉有点老,所以还是装个新的玩吧。
安装基本靠官网文档
首先下载一个安装工具,解压,执行perl install-tl 。
这里要看一下安装目录是否有权限,texlive的安装不需要root权限,但是默认安装目录是/usr/local/texlive/2020,最后一级目录是区分不同版本的,所以只要创建texlive目录,然后保证有权限就行了。
然后i开始安装,看着好像要下载四千多个文件,我使用的默认的镜像,速度还挺快的。主要看下载安装工具的时候速度就挺快。
还有gui版本的安装工具,包括安装完成后gui工具的使用,这个需要perl的tk库,sudo apt-get install perl-tk进行安装。比如:tlmgr -gui
更新系统使用命令:tlmgr update -all
Read more...
R语言ubuntu编程环境安装
第一步添加需要的密钥:
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9
第二步,选择安装镜像网站,添加软件源
sudo add-apt-repository "deb https://mirrors.tuna.tsinghua.edu.cn/CRAN/bin/linux/ubuntu $(lsb_release -cs)-cran40/"
第三步,安装R语言包
sudo apt install r-base
第四步,验证:
终端输入R,启动交互模式。
print("hello world;")
Read more...
Openstack Neutron组件服务(neutron-metadata-agent服务)
供应商网络依赖的几个服务:
neutron-server.service
neutron-linuxbridge-agent.service
neutron-dhcp-agent.service
neutron-metadata-agent.service
自服务网络除了上边的几个服务外还依赖 neutron-l3-agent.service。
从这里也能看出,自服务网络支持三层模拟,这也是主要区别。自服务可以实现的功能就比较多,比如vxlan,FWaaS,LBaaS等。
先看看neutron-metadata-agent服务,这个服务主要功能是实例启动的时候为cloud-init获取metadata的时候转发用的。因为实例所在网络跟nova-api网络肯定不通的,所以需要一个中间转发,起这个作用的就是neutron-metadata-agent服务。看网上从实例到neutron-metadata-agent服务,中间还经过了haproxy,haproxy是l3-agent或者dhcp-agent启动的,这个也许也是分不同网络类型正好不同(但是我看官方安装文档,两种网络方式配置都是使用dhcp来启动的metadata服务, 默认是通过l3-agent启动)。然后由haproxy转发给neutron-metadata-aget,然后neutron-metadata-agent转发给nova-api-metadata服务。
服务启动命令为/usr/bin/neutron-metadata-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/metadata_agent.ini
很多小模块过掉了,必须要看的时候再梳理吧。
主要是启动一个UnixDomainMetadataProxy。然后调用了agent_utils.UnixDomainWSGIServer启动,在文件neutron/agent/linux/utils.py 里,这个文件定义了好多不同类型的agnet。不得不说Openstack模块封装的太好了,接口封装的好,看起来就基本靠猜就可以了。看代码是启动了一个wsgi服务,handler为MetadataProxyHandler。然后调用_init_state_reporting,这个我看可以设置心跳,主要上报了监听的地址端口之类的信息,感觉也就监控或者排查问题有用。有个agent_rpc/context,也不知道往哪里上报的,先记住不看了。
MetadataProxyHandler里也有一个rpc(MetadataPluginAPI)/context,感觉这里不知道不行,靠猜也许行。
精简了就两行代码
instance_id, tenant_id = self._get_instance_and_tenant_id(req)
return self._proxy_request(instance_id, tenant_id, req)
第一行从header里获取请求的信息,得到实例id,我看还做了rpc调用,具体获取啥先不看了。
第二行是转发请求,把实例id和租户id,通过header传递,用requests模块发送请求给nova。返回内容无误后,返回给wsgi,请求就结束了。
好多细节没看,不过不影响流程,整个流程就是一个转发,涉及配置和验证,还有rpc没看。整体没啥复杂流程,就先这样了。
Read more...
linux系统调用sendfile和splice简单分析
零拷贝不是一个新技术了,之前一直接触不到这么底层的技术,最近看的比较多,所以从代码上研究了一下。
在应用程序做数据传输等操作涉及系统调用,而为了提高性能,就是从减少系统调用次数和减少内核空间和用户空间的数据拷贝次数入手的。
具体的我也没看代码,都是从网上总结学来的。
像mmap方式,是减少了内核空间和用户空间的数据拷贝,使用映射还是指针的能够共享内核空间。但涉及比如把一个文件内容通过网络发送的操作,还涉及内核空间的数据拷贝。
sendfile和splice就是解决内核空间的数据copy的,我看linux手册是page buffer指针的复制,所以没有做数据的copy。指针是通过pipe buffer存储的。
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
ssize_t sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count);
这俩的区别是sendfile64适合传送大文件,offset类型也决定了适合做大文件的偏移用。但不仅仅是这里,看源码,sendfile指定offset之后,会设置复制的最大值为MAX_NON_LFS,这个值我没找,但是类型初步判断加文档判断来说,最大不到2G(看文档是不到2G).(后来还是去找了,#define MAX_NON_LFS ((1UL<<31) - 1), 文档写的是0x7ffff000 (2,147,479,552) )
我看了一下函数实现的源码,尽量只看流程,不去细看实现,看看优化能注意的点。
通过看源码,发现最好是不指定offset这个参数,因为指定这个参数后,会多两次的内核函数调用,涉及用户空间和内核空间的数据拷贝,get_user,put_user,copy_from_user。然后统一调用do_sendfile函数。而如果offset为NULL的时候,在do_sendfile函数里,是通过文件的offset来复制数据的。所以尽量不指定offset是最好的,但如果提前设置文件offset还要涉及系统调用,具体权衡就不知道了。
在do_sendfile里没啥可以细讲的,流程大部分能猜到什么意思。主要最后调用do_splice_direct。
这里有个疑问就是,为什么offset要用指针类型,而不能直接传一个数字,我猜可能是历史遗留问题吧,可能接口没办法变动了。
do_splice_direct函数跟splice是在一个文件,可以差不多猜到,俩的实现原理是一样的了。
do_splice_direct里splice_desc sd定义输出文件的信息。
然后调用了splice_direct_to_actor,这里有一个pipe = current->splice_pipe;这个pipe是在linux的进程管理的pcb(task_struct)中,这里边有一个splice_pipe,用来存储splice()上一次使用的过的pipe。这里是判断如果current->splice_pipe不存在,就新创建一个,然后缓存到current->splice_pipe。然后调用do_splice_to,流程跟splice复制文件到pipe的流程差不多。
splice里直接调用do_splice,这里分三种情况,in和out都有pipe时,调用splice_pipe_to_pipe;in为pipe时调用do_splice_from,out为pipe时调用do_splice_to。这俩单个的也涉及offset的用户空间和内核空间复制的问题。
do_splice_from我直接看的default_file_splice_write,调用splice_from_pipe。里边初始化splice_desc sd,存了要写的文件信息,调用__splice_from_pipe,splice_from_pipe_feed里是将pip内容关联复制到文件。
do_splice_to也是直接看default_file_splice_read,初始化一个结构体splice_pipe_desc spd,看起来是存储pagebuffer信息的,具体看不太懂,也没去查,初始化spd空间,kernel_readv应该是用来吧in的page buffer内容的指针存入spd了,nr_pages_max = PIPE_DEF_BUFFERS这个值是16(看文档在内核版本2.6.35之后,可以通过fcntl的F_GETPIPE_SZ和F_SETPIPE_SZ进行设置),好像是最大页数,最后调用splice_to_pipe(pipe, &spd);好像就是从spd里刚保存的页信息关联复制数据到pipe。
vmsplice支持从用户空间复制数据到pipe,反方向的复制也支持,但是是内存数据的真复制。
tee复制管道内容,从一个复制到另一个
总结一下就是,文件的传输使用sendfile比较好,他会缓存pipe,并且少一次的系统调用。如果用splice,需要先从一个文件到pipe,然后pipe到另一个文件,虽然也没有真正复制,但是系统调用是两次。
splice可以实现类似代理服务器数据转发的功能,使用一个pipe连接两个socket。
上边说的都是PIPESIZE。在Linux 2.6.11之前,PIPESIZE和PIPEBUF实际上是一样的。在这之后,Linux重新实现了一个管道缓存,并将它与写操作的PIPEBUF实现成了不同的概念,形成了一个默认长度为65536字节的PIPESIZE,而PIPEBUF只影响相关读写操作的原子性,一般为page大小,内核每次操作量。PIPESIZE的最大值在/proc/sys/fs/pipe-max-size里进行设置。从Linux 2.6.35之后,在fcntl系统调用方法中实现了F_GETPIPE_SZ和F_SETPIPE_SZ操作,来分别查看当前管道容量和设置管道容量。
Read more...
ubuntu里修改默认jdk版本-update-alternatives
昨天下了一个软件,需要jdk8版本的,我之前开发是用的openjdk11版本的。就想找找怎么安装多个版本的,我之前知道可以知道path环境变量改变,就想找找有没有类似多版本管理的软件。
然后找到一个系统级别的update-alternatives,然后执行update-alternatives --config java,可以进行java版本的选择,我发现我之前安装过java8的jre了版本了。也没有切换,直接复制路径去执行的jar包。
然后就研究了一下update-alternatives 命令。配置文件目录为/var/lib/dpkg/alternatives/java
涉及的原理就是通过文件软链接来实现版本的切换。
ls -alh /usr/bin/java
lrwxrwxrwx 1 root root 22 7月 22 2019 /usr/bin/java -> /etc/alternatives/java
ls -alh /etc/alternatives/java
lrwxrwxrwx 1 root root 43 7月 22 2019 /etc/alternatives/java -> /usr/lib/jvm/java-11-openjdk-amd64/bin/java
安装软件的时候会调用update-alternatives,看文档是在执行postinst 和prerm脚本的时候,自动设置的时候会根据权重选择一个版本或者软件。
Read more...
pyenv安装本地源码包的方法
先说一下pyenv的安装方式,只有两步,第一步是将github项目clone到目录,第二步是添加环境变量。所以pyenv完全可以离线安装,比如操作系统版本一致的时候,直接把装好的pyenv环境和virtualenv环境复制到目标系统就可以了。然后添加一下环境变量。
我之前安装过pyenv了,更新pyenv进入pyenv目录后,执行git pull。
然后我复制了一份新的代码,改变环境变量,切换到新pyenv目录。然后卸载之前直接安装的python版本。pyenv uninstall 3.7.3
进入.pyenv_bak,mkdir cache.将源码包放到cache目录下。
进入.pyenv_bak/plugins/python-build/share/python-build目录,编辑3.7.3文件
#require_gcc
prefer_openssl11
export PYTHON_BUILD_CONFIGURE_WITH_OPENSSL=1
install_package "openssl-1.1.0j" "https://www.openssl.org/source/old/1.1.0/openssl-1.1.0j.tar.gz#31bec6c203ce1a8e93d5994f4ed304c63ccf07676118b6634edded12ad1b3246" mac_openssl --if has_broken_mac_openssl
install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline --if has_broken_mac_readline
if has_tar_xz_support; then
install_package "Python-3.7.3" "https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tar.xz#da60b54064d4cfcd9c26576f6df2690e62085123826cff2e667e72a91952d318" ldflags_dirs standard verify_py37 copy_python_gdb ensurepip
else
install_package "Python-3.7.3" "https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz#d62e3015f2f89c970ac52343976b406694931742fbde2fed8d1ce8ebb4e1f8ff" ldflags_dirs standard verify_py37 copy_python_gdb ensurepip
fi
改成
install_package "Python-3.7.3" "/root/.pyenv_bak/cache/Python-3.7.3.tar.xz" ldflags_dirs standard verify_py37 copy_python_gdb ensurepip
安装
pyenv install 3.7.3
安装完成后执行pyenv virtualenvwrapper,我发现需要重新安装这个插件,不知道为什么。我之前是安装了的,可能版本问题。
然后基本就可以了。virtualenv也是可以直接复制的,所以基本可以复制分发了。
Read more...