面试自我介绍五句话公式:
我是谁+从哪里来+我做过什么+有什么成绩+为什么能胜任
Hexo TroubleShooting
Nginx
配置依赖库。
gcc(GNU Compiler Collection)
pcre依赖库
zlib依赖库
SSL依赖库
1 | yum install gcc pcre-devel zlib zlib-devel openssl openssl-devel |
安装NGINX
官网下载地址: http://nginx.org/en/download.html
—> 解压1
tar -zxvf nginx-1.14.2.tar.gz
z(gz格式)j(bz2格式)x(解压)v(显示所有过程)f(使用档案名称命名)
—> configure
进入解压目录下1
./configure
—>编译1
2make
make install
启动和停止
1 | /nginx/sbin/nginx |
—>查看进程1
ps -ef | grep nginx
访问index.html页面,404
—>检查端口1
telnet 127.0.0.1 8080
显示Connection closed by foreign host
—>查看和关闭防火墙1
2firewall-cmd --state
systemctl stop firewalld.service
—>服务开机启动1
2systemctl disable firewalld.service
systemctl enable nginx.service
手动下载源码,并编译安装的是没有nginx.service的,手动创建1
vi /lib/systemd/system/nginx.service
编辑内容如下1
2
3
4
5
6
7
8
9
10
11
12
13[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
web服务及反向代理
/usr/local/nginx/nginx.conf1
2
3
4
5
6
7
8
9
10 server {
listen 8080; #nginx服务器的代理端口
server_name _;
location / {
proxy_pass http://172.18.78.14:6080; #需要反向代理的IP地址+端口
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
负载均衡
代理服务
Linux网卡重命名
查看RedHat版本1
cat /etc/redhat-release
1
yum install nginx
error:cannot find a valid baseurl
ping
connect:network is unreachable
ls /etc/sysconfig/network-scripts/
ifcfg-enp0s3 ifcfg-lo ….
其中ifcfg-lo是localhost配置
将第一个配置文件重命名1
mv ifcfg-enp0s3 ifcfg-eth0
查看网卡1
ip add
显示了lo和enp0s3
修改默认网卡设置
编辑/etc/default/grub文件,在GRUB_CMD_LINE_LINUX=””项中,插入”net.ifnames=0 biosdevname=0”
修改ip配置
注意1
DEVICE=eth0
1
ONBOOT=no //设置开机启动网卡,将值修改为“yes”
1
BOOTPROTO=static //默认为no,修改为static
重启
service network restart
reboot
video和视频流
直播原理
协议
H5 video标签
直播流的制作
Nginx+ffmpeg
安装
下载RTMP模块并重编译nginx
官方源代码https://github.com/arut/nginx-rtmp-module.git
配置
1 | ./configure --prefix=/usr/local/nginx --add-module=~/nginx-rtmp-module --with-http_ssl_module |
编译并安装
1 | make && make install |
nginx reload后报“open() “/usr/local/nginx/logs/nginx.pid” failed”,执行下面的命令,指定nginx的configure路径
1 | ./nginx -c /usr/local/nginx/conf/nginx.conf |
编译通过nginx可访问,还没完,配置nginx.conf,在末尾添加rtmp模块配置:
1 | rtmp{ |
hls_path是分割文件存储路径
在http模块中添加服务路径1
2
3
4
5
6
7
8
9
10
11
12http {
server {
location /hls{
types{
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /usr/local/userdata/live;
add_header Cache-Control no-cache
}
}
}
安装流媒体文件转换工具ffmpeg
官方release:http://www.ffmpeg.org/download.html#releases
解压1
tar jxvf ffmpeg-4.1.3.tar.bz2
执行configure报“yasm/nasm not found or too old. Use —disable-x86asm for a crippled build”,ffmpeg默认的编译器未安装,需使用—disable-x86asm
将本地视频文件通过nginx推流
本地视频文件kon.mp4
推送RTMP流
1 | ffmpeg -re -i test.mp4 -vcodec libx264 -acodec acc -f flv rtmp://127.0.0.1:1935/rtmplive/rtmp |
推送HLS流
1 | ffmpeg -re -i test.mp4 -vcodec libx264 -acodec acc -f flv rtmp://127.0.0.1:1935/hls/stream |
这里有一个关于编码器的坑
vcodec acodec 分别指明了视频、音频的编码器,其实这里可以用copy也就是不需要转码,从官方GitHub下载安装的ffmpeg是没有libx264的编码器的,故而在执行上述推流命令时报unkown encoder libx264
而通用的h.264视频编码器是叫x264:https://www.videolan.org/developers/x264.html
安装x264需要将类库提供给外部应用程序(如ffmpeg)1
2
3./configure –enable-shared
make && make install
配置编译的时候最好有—prefix指明安装路径,否则一般默认到/usr/local/lib路径下
需要将/usr/local/lib路径加入共享库配置文件/etc/ld.so.conf中1
2
3echo "/usr/local/lib" >> /etc/ld.so.conf
ldconfig
编译安装含外部解码器的FFmpeg1
2
3./configure --enable-static --enable-gpl --enable-libx264 --extra-cflags=-I/usr/local/include --extra-ldflags=-L/usr/local/lib
make && make install
redis
概念
(略)
方法
1 | keys * |
redis作为认证token数据库
ticket=(accountid, token)
centos安装Redis
参考:Linux 平台将 Redis 设置为服务并开机自启动
服务部署好之后,若无法远程访问
首先检查防火墙设置1
2
3systemctl status firewalld # 查看防火墙状态
firewall-cmd --zone= public --query-port=6379/tcp # 查询防火墙端口状态
firewall-cmd --zone=public --add-port=6379/tcp --permanent # 永久开发端口及协议
确认是否绑定服务主机ip 参考 处理CentOS 7.2 x64端口不通的问题
远程访问
修改/etc/redis/redis.conf1
2# 注释掉或将其改为服务器静态ip
# bind 127.0.0.1 ::1
DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients…..
受保护的模式,改为no1
protected-mode no
JMS
Angular自定义控件
ControlValueAccessor接口
定义一个接口,该接口充当 Angular 表单 API 和 DOM 中的原生元素之间的桥梁。实现此接口以创建与 Angular 表单集成的自定义表单控件指令, from Angular Doc
删除线小注:见下文“关于原生控件”1
2
3
4
5
6
7// angular2/packages/forms/src/directives/control_value_accessor.ts
export interface ControlValueAccessor {
writeValue(obj: any): void;
registerOnChange(fn: any): void;
registerOnTouched(fn: any): void;
setDisabledState?(isDisabled: boolean): void;
}
- writeValue(obj: any):该方法用于将宿主传入的新值写入自定义组件的视图或 DOM 属性。
- registerOnChange(fn: any):设置当控件接收到来自宿主的 change 事件后,调用的函数 一般将其对接到input控件的ngOnChange响应事件上
- registerOnTouched(fn: any):设置当控件接收到 touched 事件后,调用的函数
- setDisabledState?(isDisabled: boolean):当控件状态变成 DISABLED 或从 DISABLED 状态变化成 ENABLE 状态时,会调用该函数。该函数会根据参数值,启用或禁用指定的 DOM 元素。
自定义的组件实现ControlValueAccessor接口,可以像原生表单控件一样使用ngModel绑定值
stackbliz demo1
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
29import {Component, OnInit, forwardRef, Input} from '@angular/core';
import {ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
@Component({
selector: 'app-custom-input',
templateUrl: './custom-input.component.html',
styleUrls: ['./custom-input.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
}
]
})
export class CustomInputComponent implements ControlValueAccessor {
onChange: any = () => {}
onTouch: any = () => {}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
input: string;
writeValue(input: string) {
this.input = input;
}
}
关于原生控件
不直接操作自定义组件 而在组件内逻辑赋值绑定值input 控件会响应 但是自定义组件的ngOnChange不会响应 即父组件绑定ngModel的值并不更新, 即逻辑赋值input还需要手动调用registerOnChange注入的外部响应事件,也就是上述范例代码的onChange变量
参考ng-zorro的select控件源码发现 在实现ControlValueAccessor的自定义组件模板中原生组件是不必要的,自定义组件可以自行管理对外暴露的ngModel的值,没有必要响应原生组件的特性
OnChange接口
A lifecycle hook that is called when any data-bound property of a directive changes. Define an ngOnChanges() method to handle the changes.当指令的任何一个可绑定属性发生变化时调用。 定义一个 ngOnChanges() 方法来处理这些变更。
实际上是自定义组件继承OnChange接口,实现ngOnChange方法,当自定义组件@Input的变量更新时,该方法响应,传入SimpleChanges类型参数,该参数是发生更新的变量的哈希表, 即1
2
3
4
5
6
7
8
9
10
11@Component({selector: 'my-cmp', template: `...`})
class MyComponent implements OnChanges {
// TODO(issue/24571): remove '!'.
@Input() prop!: number;
@Input() data:any
ngOnChanges(changes: SimpleChanges) {
const {prop, data} = changes
// prop and data is an SimpleChange boject which contains the old and the new value...
}
}
SimpleChanges是SimpleChange类型的map1
2
3
4
5
6
7
8
9
10export declare class SimpleChange {
previousValue: any;
currentValue: any;
firstChange: boolean;
constructor(previousValue: any, currentValue: any, firstChange: boolean);
/**
* Check whether the new value is the first value assigned.
*/
isFirstChange(): boolean;
}
Caution! ngOnChange的底层逻辑是使用‘===’判断前后值的,因此引用类型的属性变化不会触发ngOnChange,workaround是将此类输入属性拆成基本值类型变量,或者在宿主更新该输入属性时赋予新的引用地址,亦或使用ngDoCheck
Angular组件交互
1 | <app-voter *ngFor="let voter of voters" |
@Input()
@Input()可以带set、get属性
1 | import { Component, Input } from '@angular/core'; |
在set、get时进行格式化等操作。
ngOnChanges()生命周期钩子是专门用来监听@Input入参的,非传入参数不会触发ngOnChanges()方法
@Output()
子组件发射事件1
2
3
4
5@Output() voted = new EventEmitter<boolean>();
vote(agreed: boolean) {
this.voted.emit(agreed);
}
模板标记子组件
1 | <h3>Countdown to Liftoff (via local variable)</h3> |
timer 作为父组件的变量,标记在子组件标签中,用以代表子组件,即可使父组件获取子组件的引用,进而可以调用子组件公用方法
该方法有局限性在于,父组件-子组件的连接必须全部在父组件的模板中进行。父组件本身的代码对子组件没有访问权。
@ViewChild()
1 | @ViewChild(CountdownTimerComponent) |
使用@ViewChild()装饰器将CountdownTimerComponent实例注入到本组件,记为私有变量timerComponent
特别注意
被注入的组件只有在 Angular 显示了父组件视图之后才能访问
下面的语法很关键1
2
3
4
5ngAfterViewInit() {
// wait a tick first to avoid one-time devMode
// unidirectional-data-flow-violation error
setTimeout(() => this.timerComponent.init(), 0);
}父组件要及时调用子组件方法进行初始化,须实现AfterViewInit生命周期钩子,且用定时器异步操作。
否则报异常1
ExpressionChangedAfterItHasBeenCheckedError
引入第三者通信
这类方法包括注入服务,借助相同父组件以及借助发布订阅可观察对象等,此处略。
SCSS
SCSS 是 Sass 3 引入新的语法,其语法完全兼容 CSS3,并且继承了 Sass 的强大功能。
将Angular项目样式由css改为scss
安装 node-sass sass-loader
修改angular.json1
2
3
4
5
6"styles": [
"src/styles.scss"
],
"default": {
"styleExt":"scss"
},
上面的修改也就看看,不做实操指导,新建ng项目时可以选择样式类型,当时选scss便可,免得多事
SCSS嵌套结构样式优先级高于非嵌套结构样式,因此可以用某元素父元素嵌套的写法覆盖该元素样式
常用新语法
map类型
1
2
3
4 $pie:(
width:125px
height:140px
)
1 width:map-get($pie, width)@import @mixin
定义一个Mixin模块
1
2
3
4
5 @mixin button{
font-size:1em;
padding:0.5em;
color:#fff
}
调用
1
2
3
4 .button-green{
@include button;
back-ground:green
}@extend
引用已定义的样式
1
2
3
4 .button-green-mini{
@extend .button-green;
width:2em
}循环语句创建样式
1
2
3
4
5
6
7
8
9 $lvlcolors:(
1:$color-danger
2:$color-orange
3:$color-warning
4:$color-blue
)
@for $lvl from 1 through 4{
.lvl#{$lvl} {background: map-get($lvlcolors, $lvl)}
}each:
1
2
3
4
5
6
7
8
9 $icons: ("eye": "\f112", "start": "\f12e", "stop": "\f12f");
@each $name, $glyph in $icons {
.icon-#{$name}:before {
display: inline-block;
font-family: "Icon Font";
content: $glyph;
}
}
issue: scss variables are not working in calc
1
2
3
4
5 .main {
width: 100%;
height: calc(100% - #{$header-height});
background: #313030;
}
伪类 icon
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 $icon:(
add:"%3Csvg%20width%3D%2218%22%20height%3D%2218%22%20viewBox...",
edit:"%3Csvg%20width%3D%2230%22%20height%3D%2230%22%20viewBox...",
delete:"%3Csvg%20width%3D%2230%22%20height%3D%2230%22%20viewBox...",
refresh:"%3Csvg%20width%3D%2230%22%20height%3D%2230%22%20viewBox..."
)
@each $key, $val in $icon{
.qqs-design-icon.icon-#{$key}{
position: relative;
padding-left: 22px;
margin-left: 4px;
&::before{
content: '';
position: absolute;
left: 0px;
bottom: calc(50% - 10px);
background: url("data:image/svg+xml," + $val + "") no-repeat top left;
width: 25px;
height: 25px;
}
}
}拼接url
1
2
3
4
5
6
7 $sites: ("twitter.com", "facebook.com", "linkedin.com");
@each $site in $sites {
a[href*="#{$site}"] {
background-image: url("/images/" + $site + ".png");
}
}总结一下就是#{}这个符号用于将变量拼接在css选择器上,包括class名,属性名等,在样式的值中,字符串与变量的拼接可以直接用“+”连接
issues
jenkins build fail
1 npm i -g node-sass
以下理解未必完全正确,但包含了若干方面的可能因素,可日后进一步探究(QQs:不太会探究):jenkins 在打包angular过程中为webpack的sass-loader安装所需包node-sass,但是缺少node-gyp,python等工具链的调用权限,因而build失败,至于npm install为什么会build,electron编译过程中也遇到过,编译对象是package中调用的c++库。对此的解决方案之一是在jenkins所在的物理机上全局安装node-sass,当下的默认版本是5.0.0,曾尝试在项目package.json中将node-sass更新为5.0.0,然而angular9中的sass-loader似乎是支持node-sass^4.0.0,因此出现“Node Sass version 5.0.0 is incompatible with ^4.0.0”的报错,应在全局重装npm i -g node-sass@4
参考
node-sass troubleshooting#Running with sudo or as root
stackoverflow:Error: Node Sass version 5.0.0 is incompatible with ^4.0.0
node-sass issues#941
Cannot download “https://github.com/sass/node-sass/releases/download/v4.13.1/win32-x64-83_binding.node”
package-lock指定了node-sass@4.13.1, 关于node-sass的release版本没有win32-x64-83_binding.node, ‘-83’为node 14的支持模块,而4.13的node-sass不支持node 14,见Node version support policy. 即此问题是由于编译环境升级到node14造成的,解决方法是安装支持node14的4.14+