centos使用yum update升级到指定小版本


参考: https://www.cnblogs.com/configure/p/10918189.html

 

提供一个搜狐镜像的7.6的yum源:

[C7.6.1810-base]
name=CentOS-7.6.1810 - Base
baseurl=http://mirrors.sohu.com/centos/7.6.1810/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1

[C7.6.1810-updates]
name=CentOS-7.6.1810 - Updates
baseurl=http://mirrors.sohu.com/centos/7.6.1810/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1

[C7.6.1810-extras]
name=CentOS-7.6.1810 - Extras
baseurl=http://mirrors.sohu.com/centos/7.6.1810/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1

[C7.6.1810-centosplus]
name=CentOS-7.6.1810 - CentOSPlus
baseurl=http://mirrors.sohu.com/centos/7.6.1810/centosplus/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1

[C7.6.1810-fasttrack]
name=CentOS-7.6.1810 - Fasttrack
baseurl=http://mirrors.sohu.com/centos/7.6.1810/fasttrack/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1

nginx反向代理时保持长连接


【场景描述】

HTTP1.1之后,HTTP协议支持持久连接,也就是长连接,优点在于在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接消耗和延迟

如果我们使用了nginx去作为反向代理或者负载均衡,从客户端过来的长连接请求就会被转换成短连接发送给服务器端。

为了支持长连接,我们需要在nginx服务器上做一些配置。

 

·【要求】

使用nginx时,想要做到长连接,我们必须做到以下两点:

  1. 从client到nginx是长连接
  2. 从nginx到server是长连接

 

对于客户端而言,nginx其实扮演着server的角色,反之,之于server,nginx就是一个client

 

·【保持和 Client 的长连接】

我们要想做到Client与Nginx之间保持长连接,需要:

  1. Client发送过来的请求携带“keep-alive”header
  2. Nginx设置支持keep-alive

 

【HTTP配置】

默认情况下,nginx已经开启了对client连接的 keepalive 支持。对于特殊场景,可以调整相关参数。

http {

keepalive_timeout 120s;        #客户端链接超时时间。为0的时候禁用长连接。

keepalive_requests 10000;    #在一个长连接上可以服务的最大请求数目

#当达到最大请求数目且所有已有请求结束后,连接被关闭。

#默认值为100

}

 

大多数情况下,keepalive_requests = 100也够用,但是对于 QPS 较高的场景,非常有必要加大这个参数,以避免出现大量连接被生成再抛弃的情况,减少TIME_WAIT。
QPS=10000 时,客户端每秒发送 10000 个请求 (通常建立有多个长连接),每个连接只能最多跑 100 次请求,意味着平均每秒钟就会有 100 个长连接因此被 nginx 关闭。

同样意味着为了保持 QPS,客户端不得不每秒中重新新建 100 个连接。

 

因此,如果用netstat命令看客户端机器,就会发现有大量的TIME_WAIT的socket连接 (即使此时keep alive已经在 Client 和 NGINX 之间生效)。

 

·【保持和Server的长连接】

想让Nginx和Server之间维持长连接,最朴素的设置如下:

http {

upstream backend {

server 192.168.0.1:8080 weight=1 max_fails=2 fail_timeout=30s;

server 192.168.0.2:8080 weight=1 max_fails=2 fail_timeout=30s;

  keepalive 300; // 这个很重要!

}

server {

listen 8080 default_server;

server_name “”;

 

location / {

proxy_pass http://backend;

proxy_http_version 1.1;                         # 设置http版本为1.1

proxy_set_header Connection “”;      # 设置Connection为长连接(默认为no)}

}

}

}

 

【upstream配置】

upstream中,有一个参数特别的重要,就是keepalive

这个参数和之前http里面的 keepalive_timeout 不一样

这个参数的含义是,连接池里面最大的空闲连接数量

 

不理解?没关系,我们来举个例子:

场景:

有一个HTTP服务,作为upstream服务器接收请求,响应时间为100毫秒。

要求性能达到10000 QPS,我们需要在nginx与upstream服务器之间建立大概1000条HTTP请求。(1000/0.1s=10000)

 

最优情况:

假设请求非常的均匀平稳,每一个请求都是100ms,请求结束会被马上放入连接池并置为idle(空闲)状态

我们以0.1s为单位:

1. 我们现在keepalive的值设置为10,每0.1s钟有1000个连接

2. 第0.1s的时候,我们一共有1000个请求收到并释放

3. 第0.2s的时候,我们又来了1000个请求,在0.2s结束的时候释放

 

请求和应答都比较均匀,0.1s释放的连接正好够用,不需要建立新连接,且连接池中没有idle状态的连接。

 

第一种情况:

应答非常平稳,但是请求不平稳的时候

4. 第0.3s的时候,我们只有500个请求收到,有500个请求因为网络延迟等原因没有进来

这个时候,Nginx检测到连接池中有500个idle状态的连接,就直接关闭了(500-10)个连接

5. 第0.4s的时候,我们收到了1500个请求,但是现在池里面只有(500+10)个连接,所以Nginx不得不重新建立了(1500-510)个连接。

如果在第4步的时候,没有关闭那490个连接的话,只需要重新建立500个连接。

 

第二种情况:

请求非常平稳,但是应答不平稳的时候

4. 第0.3s的时候,我们一共有1500个请求收到

但是池里面只有1000个连接,这个时候,Nginx又创建了500个连接,一共1500个连接

5. 第0.3s的时候,第0.3s的连接全部被释放,我们收到了500个请求

Nginx检测到池里面有1000个idle状态的连接,所以不得不释放了(1000-10)个连接

 

造成连接数量反复震荡的一个推手,就是这个keepalive 这个最大空闲连接数

上面的两种情况说的都是 keepalive 设置的不合理导致Nginx有多次释放与创建连接的过程,造成资源浪费。

 

keepalive 这个参数设置一定要小心,尤其是对于 QPS 要求比较高或者网络环境不稳定的场景,一般根据 QPS 值和 平均响应时间能大致推算出需要的长连接数量。

然后将keepalive设置为长连接数量的10%到30%。

 

【location配置】

http {

server {

location / {

proxy_pass http://backend;

proxy_http_version 1.1;                         # 设置http版本为1.1

proxy_set_header Connection “”;      # 设置Connection为长连接(默认为no)

}

}

}

HTTP 协议中对长连接的支持是从 1.1 版本之后才有的,因此最好通过 proxy_http_version 指令设置为 1.1。

HTTP1.0不支持keepalive特性,当没有使用HTTP1.1的时候,后端服务会返回101错误,然后断开连接

 

而 “Connection” header 可以选择被清理,这样即便是 Client 和 Nginx 之间是短连接,Nginx 和 upstream 之间也是可以开启长连接的。

 

【另外一种高级方式】

http {

map $http_upgrade $connection_upgrade {

default upgrade;

” close;

}

upstream backend {

server 192.168.0.1:8080 weight=1 max_fails=2 fail_timeout=30s;

server 192.168.0.2:8080 weight=1 max_fails=2 fail_timeout=30s;

keepalive 300;

}

server {

listen 8080 default_server;

server_name “”;

location / {

proxy_pass http://backend;

 

proxy_connect_timeout 15;       #与upstream server的连接超时时间(没有单位,最大不可以超过75s)

proxy_read_timeout 60s;           #nginx会等待多长时间来获得请求的响应

proxy_send_timeout 12s;           #发送请求给upstream服务器的超时时间

proxy_http_version 1.1;

proxy_set_header Upgrade $http_upgrade;

proxy_set_header Connection $connection_upgrade;

}

}

}

 

http里面的map的作用是:

让转发到代理服务器的 “Connection” 头字段的值,取决于客户端请求头的 “Upgrade” 字段值。

如果 $http_upgrade没有匹配,那 “Connection” 头字段的值会是upgrade

如果 $http_upgrade为空字符串的话,那 “Connection” 头字段的值会是 close

 

【补充】

NGINX支持WebSocket。

对于NGINX将升级请求从客户端发送到后台服务器,必须明确设置Upgrade和Connection标题。

这也算是上面情况所非常常用的场景。

HTTP的Upgrade协议头机制用于将连接从HTTP连接升级到WebSocket连接,Upgrade机制使用了Upgrade协议头和Connection协议头。

为了让Nginx可以将来自客户端的Upgrade请求发送到后端服务器Upgrade和Connection的头信息必须被显式的设置

 

【注意】

在nginx的配置文件中,如果当前模块中没有proxy_set_header的设置,则会从上级别继承配置

继承顺序为:http, server, location

 

如果在下一层使用proxy_set_header修改了header的值,则所有的header值都可能会发生变化,之前继承的所有配置将会被丢弃

所以,尽量在同一个地方进行proxy_set_header,否则可能会有别的问题。

 

·【参考】

Nginx中文官方文档: http://www.nginx.cn/doc/

测试参考文档: https://www.lijiaocn.com/问题/2019/05/08/nginx-ingress-keep-alive-not-work.html

keep-alive参考文档: https://wglee.org/2018/12/02/nginx-keepalive/

mysql命令行不再提醒警告


在Linux命令行里输入mysql 用户密码就会提示:

Warning: Using a password on the command line interface can be insecure.

即使我们用2>想给它重定向也无济于事。

有一个方法可以隐藏掉这个警告。

 mysql_config_editor set --user=root --socket=/tmp/mysql.sock --password

输入密码即可,这样就可以把密码保存到一个配置文件里 ~/.mylogin.cnf, 这个文件不能直接cat查看

以后再次使用mysql时,直接敲mysql命令即可完成登录。

搭建一个局域网http的yum源


1. 先创建一个目录,作为存在rpm包的目录
mkdir /data/yumdata
2. 拷贝ISO镜像文件中的rpm包到/data/yumdata/
mount /dev/cdrom /mnt/
cp /mnt/Packages/*rpm /data/yumdata
【小常识】 可以在/data/yumdata/下面创建子目录,然后把rpm包放到子目录下面,也可以被识别到
3. 创建repository
createrepo /data/yumdata/
如果rpm包有增加,需要执行
createrepo --update /data/yumdata/
4. 安装nginx,提供http服务
yum install epel-release
yum install nginx
当然,如果无法使用yum,需要下载nginx源码包,并编译安装
配置nginx.conf,使其可以通过IP地址访问到/data/yumdata
参考配置文件:
    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /data/yumdata;

        location / {
            autoindex on;  //这一步必须要有,这是为了提供目录浏览
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
5. 客户端上配置repo文件
cd /etc/yum.repos.d
mkdir bak
mv *.repo  bak/  //把系统自带的repo挪走
vim my.repo //内容如下
[aming]
name=myserver
baseurl=http://192.168.133.140
gpgcheck=0
enabled=1
6.  做一个镜像yum源
比如可以把系统默认的源给镜像到局域网来,思路是用rsync工具把远程的rpm包同步到这台局域网的对应目录下即可。
rsync -av rsync://mirrors.ustc.edu.cn/centos/7/os/x86_64/Packages/  /data/yumdata/
7. 当局域网的rpm库有更新时,除了服务端执行“createrepo  –update /data/yumdata/”外,客户端上也需要执行
yum  clean all   //删除缓存

Nginx代理tomcat https跳转到http


问题

网站采用了 Nginx 反向代理 Tomcat 的方式来负载均衡。

Nginx使用https,默认端口443。Tomcat使用http,端口8080

结果今天后台操作停留时间过长session超时后,跳转到登录页面时出现无法访问错误。如图:

http_error

分析

可以看到,出错的原因应该是跳转的时候加上了web默认80端口,而https默认的端口并不是80,所以导致无法访问。

后台无session时跳转代码:

  1. requestURL = HttpUtils.encodeUrl(requestURL);
  2. String path = request.getContextPath();
  3. String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path
  4. + "/";
  5. return basePath + "user/login?goUrl=" + requestURL;

代码跳转的是绝对路径,包括schema和port,问题应该就在这里。

经过调试发现获取到的request.getScheme()总是http而非实际的https,相应的request.getServerPort()也就成了80。

端口是80而非Tomcat本身的8080说明获取到的确实是nginx转发过来的请求,那schema为什么得不到呢?

解决

通过查找资料,发现nginx请求转发时必须设置proxy_set_header才能让被代理的tomcat获取到正确的客户端ip等信息。

但是之前已经设置过nginx的proxy_set_header,而获取ip等也毫无问题:

  1. proxy_set_header X-Real-IP $remote_addr;
  2. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  3. proxy_set_header Host $http_host;
  4. proxy_set_header X-Forwarded-Proto $scheme;
  5. proxy_redirect http:// $scheme://;
  6. proxy_pass http://localhost:8080;#转向tomcat处理

上面有一行设置了proxy_redirect,所以浏览器地址栏的schema仍然是https.

接着查找资料,发现要传递schema,在Tomcat端也需要相应配置。

  1. <Engine>
  2. <Valve className="org.apache.catalina.valves.RemoteIpValve"
  3. remoteIpHeader="X-Forwarded-For"
  4. protocolHeader="X-Forwarded-Proto"
  5. protocolHeaderHttpsValue="https"/>
  6. </Engine >

加上后,重启Tomcat,一切正常了!

你不知道的vim小秘密


大家先了解一些背景知识:

1) 给文件增加了i权限,那文件不能被更改,不能删除,也不能修改名字以及权限。

2) 给文件增加a权限,文件可以追加内容,不能删除,不能修改内容,不能修改名字以及权限。

3) vim一个文件,如果不正常退出,再次编辑时是会提示一些信息的,并且有一个隐藏的文件.xxx.swp

了解以上知识后,再来看下面的现象:

1) 如果给一个文件增加a权限,用vim编辑文件,增加内容(注意是在文件末尾增加内容,不要修改其他内容),并不会成功。

2) 如果给一个目录增加i权限或者a权限,在该目录下面vim一个文件,更改文件内容可以正常保存。

既然a权限可以追加内容,那为何vim一个文件在末尾增加内容不能成功?既然i权限不能修改,那为何在目录里面变更文件内容却可以成功?

关于这两点,你有没有疑惑?下面我们来分析原因。

先不管i或者a权限,在一个没有i或者a权限的目录下,编辑一个没有i或者a权限的文件,用strace来查看其执行过程。

mkdir /tmp/test

strace vim /tmp/test/aminglinux.txt 2>/tmp/vim.log

写入一个数字1,然后保存退出。再来查看vim.log的内容。

less /tmp/vim.log

大部分内容你不用关心,只需要看这几行:

stat(“/tmp/test/aminglinux.txt”, 0x7fff072ecb10) = -1 ENOENT (No such file or directory)

access(“/tmp/test/aminglinux.txt”, W_OK) = -1 ENOENT (No such file or directory)

open(“/tmp/test/aminglinux.txt”, O_RDONLY) = -1 ENOENT (No such file or directory)

readlink(“/tmp/test/aminglinux.txt”, 0x7fff072eb360, 4095) = -1 ENOENT (No such file or directory)

open(“/tmp/test/.aminglinux.txt.swp”, O_RDONLY) = -1 ENOENT (No such file or directory)

open(“/tmp/test/.aminglinux.txt.swp”, O_RDWR|O_CREAT|O_EXCL, 0600) = 3

open(“/tmp/test/.aminglinux.txt.swx”, O_RDONLY) = -1 ENOENT (No such file or directory)

open(“/tmp/test/.aminglinux.txt.swx”, O_RDWR|O_CREAT|O_EXCL, 0600) = 4

unlink(“/tmp/test/.aminglinux.txt.swx”) = 0

unlink(“/tmp/test/.aminglinux.txt.swp”) = 0

stat(“/tmp/test/.aminglinux.txt.swp”, 0x7fff072ec310) = -1 ENOENT (No such file or directory)

lstat(“/tmp/test/.aminglinux.txt.swp”, 0x7fff072ec3e0) = -1 ENOENT (No such file or directory)

lstat(“/tmp/test/.aminglinux.txt.swp”, 0x7fff072ec8a0) = -1 ENOENT (No such file or directory)

open(“/tmp/test/.aminglinux.txt.swp”, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, 0600) = 3

stat(“/tmp/test/aminglinux.txt”, 0x7fff072eac40) = -1 ENOENT (No such file or directory)

stat(“/tmp/test/aminglinux.txt”, 0x7fff072ebe20) = -1 ENOENT (No such file or directory)

stat(“/tmp/test/aminglinux.txt”, 0x7fff072eadf0) = -1 ENOENT (No such file or directory)

write(1, “\”/tmp/test/aminglinux.txt\””, 26) = 26

stat(“/tmp/test/aminglinux.txt”, 0x7fff072ec050) = -1 ENOENT (No such file or directory)

open(“/tmp/test/aminglinux.txt”, O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4

stat(“/tmp/test/aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=2, …}) = 0

stat(“/tmp/test/aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=2, …}) = 0

unlink(“/tmp/test/.aminglinux.txt.swp”) = 0

看起来乱乱的,其实大概的过程就是vim  /tmp/test/aminglinux.txt时,先看有没有.aminglinux.txt.swp以及.aminglinux.txt.swx,因为这两个文件就是vim产生的临时文件,swp先产生,如果swp存在就产生第二个swx。写入的内容先存到swp里,当保存退出vim时,再把swp的内容存到aminglinux.txt里,最后删除掉swp文件。

有了这个认识之后,我们再来分析上面提到的现象1。如果文件给了a权限,那么在编辑该文件时,会产生swp文件,当保存退出时,swp文件内容会写入该文件,这相当于更改该文件,很线上a权限是不允许的。

再来分析现象2,按照我们的推测,如果目录给了a权限,增加文件没问题,也就是说产生swp或者swx文件没有问题,当然把swp或者swx内容写入到文件里时也不会有问题,但swp或者swx文件却不会被删除了,所以再次编辑文件时就会提示临时文件已经存在了。但这并不会影响修改文件内容。

如果给目录设置了i权限的话,vim编辑文件,要产生swp或swx肯定会出错啊,但为何依然能正常编辑文件? 下面继续用strace来分析一下。

chattr +i  /tmp/test

strace vim /tmp/test/aminglinux.txt 2> /tmp/vim.log

看vim.log里面和aminglinux.txt相关的信息

stat(“/tmp/test/aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=4, …}) = 0

stat(“/tmp/test/aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=4, …}) = 0

stat(“/tmp/test/aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=4, …}) = 0

stat(“/tmp/test/aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=4, …}) = 0

access(“/tmp/test/aminglinux.txt”, W_OK) = 0

open(“/tmp/test/aminglinux.txt”, O_RDONLY) = 3

readlink(“/tmp/test/aminglinux.txt”, 0x7fff49efc6f0, 4095) = -1 EINVAL (Invalid argument)

open(“/tmp/test/.aminglinux.txt.swp”, O_RDONLY) = -1 ENOENT (No such file or directory)

open(“/tmp/test/.aminglinux.txt.swp”, O_RDWR|O_CREAT|O_EXCL, 0600) = -1 EACCES (Permission denied)

stat(“/tmp/test/.aminglinux.txt.swp”, 0x7fff49efd6a0) = -1 ENOENT (No such file or directory)

lstat(“/tmp/test/.aminglinux.txt.swp”, 0x7fff49efd770) = -1 ENOENT (No such file or directory)

lstat(“/tmp/test/.aminglinux.txt.swp”, 0x7fff49efdc30) = -1 ENOENT (No such file or directory)

open(“/tmp/test/.aminglinux.txt.swp”, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, 0600) = -1 EACCES (Permission denied)

readlink(“/tmp/test/aminglinux.txt”, 0x7fff49efc6f0, 4095) = -1 EINVAL (Invalid argument)

open(“/root/tmp/aminglinux.txt.swp”, O_RDONLY) = -1 ENOTDIR (Not a directory)

open(“/root/tmp/aminglinux.txt.swp”, O_RDWR|O_CREAT|O_EXCL, 0600) = -1 ENOTDIR (Not a directory)

stat(“/root/tmp/aminglinux.txt.swp”, 0x7fff49efd6a0) = -1 ENOTDIR (Not a directory)

lstat(“/root/tmp/aminglinux.txt.swp”, 0x7fff49efd770) = -1 ENOTDIR (Not a directory)

lstat(“/root/tmp/aminglinux.txt.swp”, 0x7fff49efdc30) = -1 ENOTDIR (Not a directory)

open(“/root/tmp/aminglinux.txt.swp”, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, 0600) = -1 ENOTDIR (Not a directory)

readlink(“/tmp/test/aminglinux.txt”, 0x7fff49efc6f0, 4095) = -1 EINVAL (Invalid argument)

open(“/var/tmp/aminglinux.txt.swp”, O_RDONLY) = -1 ENOENT (No such file or directory)

open(“/var/tmp/aminglinux.txt.swp”, O_RDWR|O_CREAT|O_EXCL, 0600) = 4

open(“/var/tmp/aminglinux.txt.swx”, O_RDONLY) = -1 ENOENT (No such file or directory)

open(“/var/tmp/aminglinux.txt.swx”, O_RDWR|O_CREAT|O_EXCL, 0600) = 5

unlink(“/var/tmp/aminglinux.txt.swx”)   = 0

unlink(“/var/tmp/aminglinux.txt.swp”)   = 0

stat(“/var/tmp/aminglinux.txt.swp”, 0x7fff49efd6a0) = -1 ENOENT (No such file or directory)

lstat(“/var/tmp/aminglinux.txt.swp”, 0x7fff49efd770) = -1 ENOENT (No such file or directory)

lstat(“/var/tmp/aminglinux.txt.swp”, 0x7fff49efdc30) = -1 ENOENT (No such file or directory)

open(“/var/tmp/aminglinux.txt.swp”, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, 0600) = 4

chmod(“/var/tmp/aminglinux.txt.swp”, 0644) = 0

open(“/tmp/test/aminglinux.txt”, O_RDONLY) = 3

stat(“/tmp/test/aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=4, …}) = 0

stat(“/tmp/test/aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=4, …}) = 0

stat(“/tmp/test/aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=4, …}) = 0

access(“/tmp/test/aminglinux.txt”, W_OK) = 0

write(1, “\”aminglinux.txt\””, 16)      = 16

stat(“aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=4, …}) = 0

access(“aminglinux.txt”, W_OK)          = 0

getxattr(“aminglinux.txt”, “system.posix_acl_access”, 0x7fff49efd050, 132) = -1 ENODATA (No data available)

stat(“aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=4, …}) = 0

open(“aminglinux.txt”, O_WRONLY|O_CREAT|O_TRUNC, 0644) = 3

chmod(“aminglinux.txt”, 0100644)        = 0

setxattr(“aminglinux.txt”, “system.posix_acl_access”, “\x02\x00\x00\x00\x01\x00\x06\x00\xff\xff\xff\xff\x04\x00\x04\x00\xff\xff\xff\xff \x00\x04\x00\xff\xff\xff\xff”, 28, 0) = 0

stat(“/tmp/test/aminglinux.txt”, {st_mode=S_IFREG|0644, st_size=6, …}) = 0

unlink(“/var/tmp/aminglinux.txt.swp”)   = 0

我相信你可以看到Permission denied的提示,这是因为当前目录有i权限,不能增加文件,也就不能在当前目录下生成临时文件。当然,vim如果遇到这样的问题,它还是会“曲线救国”的,于是先找/root/tmp/,但是并没有该目录,只好继续找/var/tmp/,这个目录存在,所以就在这个目录里生成了临时文件(并不是隐藏的)。后面的操作就不用多说了。

既然vim可以在/var/tmp/下生成临时文件,自然也可以在已经设置了i权限的目录里编辑文件的,这样现象2也解释通了。上面罗嗦了这么多,其实我就想表达如下观点:

vim编辑文件时,会在该文件所在目录生成临时隐藏文件.swp和.swx,如果那目录不可写就会到/root/tmp/下或者/var/tmp/下生成临时文件(非隐藏),当编辑的文件保存后,临时文件删除。

这个命令你看得懂么


直接上命令

history 1 | { read x cmd; echo “$cmd”; }

对于read命令的了解,仅限于在shell脚本中使用read -p,对于这种用法从来没用过,更不知道它的含义。

今天抽空琢磨了一下,终于搞明白了来龙去脉。先来写几个命令吧:

# read a b c

1 2 3

# echo $a

1

# echo $b

2

# echo $c

3

# read x y

1 2 3

# echo $x

1

# echo $y

2 3

到这,也许你似乎看出一些门道了。read命令,后面跟的是变量名,可以是1个,也可以是多个,用空格分隔。回车后,输入的字符就是在给这些变量赋值,输入的字符串也需要用空格分隔,如果和上面的变量名一个一个地对应,那么这样就一个一个地赋值了。

如果没有对应呢?通过上面的命令也可以发现,如果值比变量多,它只对应前面的。例如,变量只有x和y,而值是1 2 3,则它把x赋值1,后面的2 3一股脑赋值给最后面的变量y。

再来一个例子吧。

# echo 1 2 3 4 5|read a b c

# echo $a

1

# echo $b

2

# echo $c

3 4 5

再回头看这条命令:

history 1 | { read x cmd; echo “$cmd”; }

管道前面,history 1表示取最后一条命令。管道后面'{ }’内是一整体,相当于一个函数,函数里面可以有多条命令,用分号分割,而且最后一条命令也必须加分号。第一条命令和'{‘之间必须要有空格。

成功转型并不是没有原因


很早之前在网上搜索linux找到了铭哥的论坛,当时也下载了铭哥分享的课程视频,并照着视频自学了一遍,将所有实验都做了一遍,距离找工作可能也还差点。

就这样过了几个月,工作上不是特别忙了,下定决心转行做专职运维,报名阿铭linux vip课程学习。

和自学相比,有一群小伙伴和你一起学习明显感觉不一样,有不明白的地方可以及时相互讨论解决,更重要的是每天都有安排学习任务,不及时的学习就落后其他同学了,特别是在职平时可能要加会儿班,只能用周末的时间来追上学习进度。

回想那会儿,真有点入魔的感觉,每天下班回来吃完饭,就开始边看视频边做笔记边实验,经常都是十二点多睡,遇到故障排错可能就得凌晨一两点才睡,上下班路上拿出笔记复习,仿佛回到了高考。

下面说说找工作的经历:刚开始投简历出去都没有什么反应,赶紧找铭哥看看是不简历写的有问题,相对来说二、三线城市职位机会少一些,找工作真得有点耐心才行。

参加的所有面试中虽然有笔试的很少,但还是建议看看面试宝典上的试题,特别是脚本、如何看待运维、运维工作内容、处理过的重大故障等,都可以在宝典上找到非常好的答案。

脚本平时一定要多练,至少要掌握思路,有的面试官会直接让你写脚本。对于简历上提到的技术点一定要非常了解,陆陆续续的面试中不断总结再回去看笔记或者动手配置,加深印象,不至于陌生。

另外,几乎没有面试者可以百分之百匹配企业岗位,所以面试中展现自己的学习能力非常重要。

最近入职运维工程师了,算是跨入运维行业了,感谢铭哥带我转行,也感谢自己3个月的付出,越努力,越幸运!祝愿大家都能找到满意的工作。

从野路子转型为专业的Linux运维


之所以这么说,是因为在现在的公司干的比较杂,感觉不算是专业的运维,虽然接触到Linux也比较长的时间了。

先简单说下自己的情况,我是从开发转过来的,因为开发做的时间也不长,由于公司职位的变动,后续阴差阳错的就开始了公司的杂七杂八的系统运维的工作,后期在Aming Linux学些了一段时间,刚开始是想找运维开发的工作,可是运维开发的经验几乎没有,于是在铭哥的建议下,找运维的工作,最后找到的工作后期要整自动化的开发,看来要好好恶补python了。

仔细算下来,接触到 IT 行业已经3年整了,在 dz 公司也默默无闻地待了三年。无论是做开发还是系统运维,都没有哪样能拿得出手的。从去年 11 月份开始正式开始准备学习Linux的各种,主要是通过阿铭Linux来学习系统运维、架构等,到现在也该结束这段旅程了。

写这些东西主要是对这段时间的面试做下总结。说来也不怕大伙笑话,从开始面试到现在,总共面试了五家公司,给 offer 的公司只有一家(囧),也就是现在将要入职的这家公司。

第一家是自如租房的,面试岗位是 Linux 运维工程师,刚开始直接面试结束,谈了挺长时间技术,个人感觉本次面试发挥的还好,面试官比较年轻,问的也不是很深,谈的比较融洽。

问完技术了,他向总监汇报后,看了我的学历是大专,就和我说了他们公司至少要得是本科以上学历,我擦,人事早干啥去了,灰头土脸的就回去了。

第二家公司便是大名鼎鼎的罗胖的公司,没错是罗辑思维,绝对是慕名而去的,大概看了下公司的招聘要求,是招运维开发的,自认为懂点开发和 Python 就不自量力的去面试了。

又是一通打击,面试官是俩人,三十多岁,也算比较亲和,第一句话就说我写的简历太罗嗦,没有重点,给提了些建议。接着开始面试,简历上写的Linux运维开发的经验非常少,自然而然得被强烈鄙视了一把,聊了几分钟就over了,送我走了,不过也有收获,临走还照了张大厅的logo。

第三家是面试的公司名字似乎是叫云校。公司做的是幼儿教育培训的,岗位是Linux高级运维工程师。面试我的是一个中年老男,秃顶,不知道是不是大牛,但至少经历了很多的人。

面试很有重点,awk,sed,grep的询问,当时他说的是三个字母的缩写,根本没想到是是说的这三剑客啊;问了keepalived的原理,vrrp的原理,kvm虚拟化的原理,vlan的含义,大概在看的你也能知道结局有多悲惨了。

当然还问了其它的好多内在底层的东西,给了个评价:我们这是招聘高级运维的,我这也顶多能算个初级的运维吧,还劝我不要做运维了,还是老老实实去做C开发吧。本来纠结的情绪又被他浇了一把火。

第四家是在中关村 E 世界,公司名称是时速云,做 docker 云计算的,冒冒失失的就去了。刚开始面试我的是个老手,问了好多 MySQL的技术,主从的各种问题,虽然有答不上来的问题,但整体回答的还算可以。

不巧,面试官接到了个电话走了,来了个年轻小伙,问了我有没有IDC运维经验,说白了就是问在机房有上架过服务器设备,果断回答没有,然后就没然后了,被打发走了。悲惨呢,还是中午没吃饭去面试的,擦。

第五家,最后一家,也是前天给了 offer 的一家公司,公司名字就不说了,是门户网站的。这次其实面试的时候也没有多大的信心,经过5轮面试官的面试,终于通过了最后的面试,在前天给发了 offer。

其实也没有写多少关于面试中的技术点,就是记录一下流水账,记录自己的面试的几次经历。但是也有收获,对面试也有了新的认识和总结。

1、写好简历,弄懂简历上写的每一条内容。

2、简历内容最好是真实的,如果没有经验,也要事先想好怎么说。

3、准备好自我介绍,感觉这点也很重要。不要指望在面试临场发挥,准备好多个自我介绍的版本,针对不同公司介绍不同的版本。

4、每一项技术点都要弄明白,我说的是你简历上写的专业技能,不能给自己挖坑,比如说精通虚拟化,精通TCP/IP,除非你真的会。

5、如果面试官和你侃侃而谈,而且说的与技术无关的话题,这时候你就要小心了,我就掉过坑了。

6、最好自己整一个个人博客,算是个加分项。

7、即使你没有经验,也要在平时积累点小项目,网上搜罗点小项目,多熟悉练习,成为自己的东西,可以当做自己的实践经验。

8、这点不算,准备想好自己公司的系统架构,即使没有也要编一个出来,参考铭哥论坛上给的一个股票网站的架构。

9、要有自信,其实其它面试的也很菜。

10、总之一句话: 准备 + 总结。

最后说下自己的薪资,16k*12,外加点绩效奖金,不过公司还行,先做一段时间历练历练。先就写这么多吧,上边都写了公司名字,不知道好不好。在这里祝各位暂时还没有找到工作的师兄弟早日找到自己理想的工作。

这个零基础很牛x


我是17年5月左右报名咱们的课程,0基础没有任何经验!

我是一名网管,工作在一家外资企业,虽说薪资待遇在同行看来还算可以,但是安逸和没有任何技术含量的工作让我感觉到岌岌可危!年初离开家,再次来到这个陌生的城市,每次离家出走父母都特别难受(各种叮嘱,各种吧家里好吃的都让我带着),(我母亲尤其是不容易,培养我们两个大学生,每次工作回家都腰疼的不行不舍得花钱去看下!我真的很愧对我的父母!)

毕竟一年也就见面个那么一两次,每次来到这边我都恨我自己为什么别人都可以拿高薪?为什么别人都可以买房子?为什么别人都可以把父母接过来享福?别人可以我也可以!我宁愿拼死在路上,也不愿安逸在现实生活中!

原本以为凭着一口流利的英语和也就那么回事的网管技术,找个1w左右的网管继续干干应该还可以吧,就这样开始各种找,各种投!一天两天一周过去了,仍然没有任何音讯。

之前企业招聘帮我找个小弟,看到很多人投给我的简历,我深有感慨:32,35,最大的38岁我可以理解,可能就是想混混日子吧才要个8k,苏州8k 接近40岁,你打算月月吃土吗?你对得起你的老婆孩子吗?哪些32-35岁的,你们怎么想的?6-8k。。。我真不忍心把他们招过来耽误他们(估计是看重欧美外资了吧)。。

时间来到了4月,我本打算再次学习学习服务器之类的专业,等我再次去网上投投简历(最主要的是看招聘要求),想确认一个方向,只要筛选1w左右的,几乎都是需要会Linux。一不干二不休,周末就去图书馆(我一直坚持到现在,每周都去图书馆)借了几本书。

我算是比较幸运就此开始接触铭哥,那本“让小白和女友都可以学会的linux教程”深深地刺激了我,小白不就是我么。开始学了一个多月吧,一直看到正则。开始有压力,同时也遇到了大家相同的问题,学着后面的忘了前面的,尤其是正则那部分,几乎全部是我凭脑袋死记硬背的!“学习不得法,累死也白搭!”~

时间就这么来到了5月,打算报铭哥的课程,我每月5.2k的房贷。真剩不下多少钱可以再次报名了,可能大家都是一次性付款的,我选择了贷款!因为我知道,未来的我一定会感谢现在的冲动!

顺利加入23期大家庭!铭哥,我不多说了,非常非常的负责任,为了专心培养我们舍弃了腾讯年薪40w的薪资,各种想法设法的搞在线考试系统,联系有条件的同学组成各个“架构组”,我真心的感觉到了我找对地方了。

学习了算是6个月吧,自己的坚持不舍,终究还是还来的一份完美的结果,我第一份真的只是打算去被虐下,让自己知道自己的不足之处,就真的把我要了。

1w转正!我认为在苏州这个薪资还算可以,最起码我算是真正的入门了。

重点是面试的内容,我已经在群内分享了我写的简历。一定要把自己挖的坑填上,一定要把自己挖的坑填上,一定要把自己挖的坑填上。我自己面试自己至少不下于10次吧,我自己也整理了好几套我们所学的架构的原理,优缺点,性能调优等等,不要求你全会,面试的时候总能说上几句吧?

其实我这几天又面试了两家。都给我了offer,昨天的甚至说的现在可以签合同不,薪资1.5w(五险一金全部按照最低来)12个开发(8个java+4个php)线上商城,我面试之后他直接说,嗯你非常适合我们这个职位,经过你说完,我感觉我们线上的这些服务都是单点?

我不想签的原因是(未来就我一个人,而且又TM(允许我使用一次tm)兼职IT的工作!也就是来个人你还得装系统)我tm想想都恶心,装系统,装你妹哇装。。。

三家面试的路子全部都是按照我简历所写来的。小伙伴们,再次提醒,自己挖的坑,埋不上就别去送死!还有三家我全部都让我画了我们公司的架构图!所以面试前一定也要准备好,万无一失,多想想自己的简历是不是还有没有想到的地方?你觉得你还会有压力么?

时光飞逝转眼下年我28,求时光慢些,饶了我那含辛茹苦的父母,拼死3年争取30岁能对得起我自己在家辛苦的父母!时光不老,23期永远不散,我永远都在23期!