【分布式应用】Filebeat+ELK 部署、logstash filter四大过滤插件

news2024/10/7 9:23:45

目录

  • 一、 Filebeat+ELK 部署
    • 1.1在 Filebeat 节点上操作
      • 1.1.1安装 Filebeat
      • 1.1.2设置 filebeat 的主配置文件
      • 1.1.3 在 Logstash 组件所在节点上新建一个 Logstash 配置文件
      • 1.1.4浏览器访问测试
  • 二 、filter四大插件
    • 2.1grok 正则捕获插件
      • 2.1.1内置正则表达式调用
    • 2.2logstash 官方一些常用的正则表达式
    • 2.3自定义正则表达式调用
  • 三、mutate 数据修改插件
    • 3.1 Mutate 过滤器常用的配置选项
    • 3.2示例
  • 四、multiline多行合并插件
  • 4.1安装multiline插件
    • 4.2使用multiline插件
  • 五、date 时间处理插件
    • 5.1时间戳详解

一、 Filebeat+ELK 部署

节点IP组件
Node1节点(2C/4G)node1/192.168.243.100Elasticsearch
Node2节点(2C/4G)node2/192.168.243.102Elasticsearch
Apache节点apache/192.168.8243.103Logstash Kibana Apache
Filebeat节点filebeat/192.168.243.104Filebeat

1.1在 Filebeat 节点上操作

1.1.1安装 Filebeat

#上传软件包 filebeat-6.7.2-linux-x86_64.tar.gz 到/opt目录
tar zxvf filebeat-6.7.2-linux-x86_64.tar.gz
mv filebeat-6.7.2-linux-x86_64/ /usr/local/filebeat

1.1.2设置 filebeat 的主配置文件

cd /usr/local/filebeat

vim filebeat.yml
filebeat.inputs:
- type: log         #指定 log 类型,从日志文件中读取消息
  enabled: true
  paths:
    - /var/log/messages       #指定监控的日志文件
    - /var/log/*.log
  tags: ["sys"]		#设置索引标签
  fields:           #可以使用 fields 配置选项设置一些参数字段添加到 output 中
    service_name: filebeat
    log_type: syslog
    from: 192.168.80.13

--------------Elasticsearch output-------------------
(全部注释掉)

----------------Logstash output---------------------
output.logstash:
  hosts: ["192.168.80.12:5044"]      #指定 logstash 的 IP 和端口

#启动 filebeat
nohup ./filebeat -e -c filebeat.yml > filebeat.out &
#-e:输出到标准输出,禁用syslog/文件输出
#-c:指定配置文件
#nohup:在系统后台不挂断地运行命令,退出终端不会影响程序的运行

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

1.1.3 在 Logstash 组件所在节点上新建一个 Logstash 配置文件

cd /etc/logstash/conf.d

vim filebeat.conf
input {
    beats {
        port => "5044"
    }
}

#filebeat发送给logstash的日志内容会放到message字段里面,logstash使用grok插件正则匹配message字段内容进行字段分割
#Kibana自带grok的正则匹配的工具:http://<your kibana IP>:5601/app/kibana#/dev_tools/grokdebugger
# %{IPV6}|%{IPV4} 为 logstash 自带的 IP 常量
filter {
  grok {
    match => ["message", "(?<remote_addr>%{IPV6}|%{IPV4})[\s\-]+\[(?<logTime>.*)\]\s+\"(?<method>\S+)\s+(?<url_path>.+)\"\s+(?<rev_code>\d+) \d+ \"(?<req_addr>.+)\" \"(?<content>.*)\""]
  }
}

output {
    elasticsearch {
        hosts => ["192.168.243.100:9200","192.168.243.102:9200"]
        index => "%{[fields][service_name]}-%{+YYYY.MM.dd}"
    }
    stdout {
        codec => rubydebug
    }
}

#启动 logstash
logstash -f filebeat.conf

在这里插入图片描述
在这里插入图片描述

1.1.4浏览器访问测试

http://192.168.243.100:5601 登录 Kibana,单击“Create Index
Pattern”按钮添加索引“httpd-*”,单击 “create” 按钮创建,单击 “Discover”
按钮可查看图表信息及日志信息。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二 、filter四大插件

  • 对于 Logstash 的 Filter,这个才是 Logstash 最强大的地方。Filter 插件也非常多,我们常用到的 grok、date、mutate、mutiline 四个插件。
    在这里插入图片描述

2.1grok 正则捕获插件

  • grok 使用文本片段切分的方式来切分日志事件

2.1.1内置正则表达式调用

%{SYNTAX:SEMANTIC}

  • SYNTAX代表匹配值的类型,例如,0.11可以NUMBER类型所匹配,10.222.22.25可以使用IP匹配。

  • SEMANTIC表示存储该值的一个变量声明,它会存储在elasticsearch当中方便kibana做字段搜索和统计,你可以将一个IP定义为客户端IP地址client_ip_address,如%{IP:client_ip_address},所匹配到的值就会存储到client_ip_address这个字段里边,类似数据库的列名,也可以把
    event log 中的数字当成数字类型存储在一个指定的变量当中,比如响应时间http_response_time,假设event log
    record如下:

总结:SYNTAX是变量值,匹配的是grok自带的正则表达式。SEMANTIC可以理解为变量名字

匹配:message: 192.168.243.100GET /index.html 15824 0.043

#可以使用如下grok pattern来匹配这种记录
%{IP:client_id_address} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:http_response_time}

在这里插入图片描述

2.2logstash 官方一些常用的正则表达式

查看官方地址

USERNAME: [a-zA-Z0-9._-]+
USER: %{USERNAME}
EMAILLOCALPART: [a-zA-Z][a-zA-Z0-9_.+-=:]+
EMAILADDRESS: %{EMAILLOCALPART}@%{HOSTNAME}
INT :(?:[+-]?(?:[0-9]+))
BASE10NUM :(?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+)))
NUMBER :(?:%{BASE10NUM})
BASE16NUM: (?<![0-9A-Fa-f])(?:[+-]?(?:0x)?(?:[0-9A-Fa-f]+))
BASE16FLOAT: \b(?<![0-9A-Fa-f.])(?:[+-]?(?:0x)?(?:(?:[0-9A-Fa-f]+(?:\.[0-9A-Fa-f]*)?)|(?:\.[0-9A-Fa-f]+)))\b

POSINT :\b(?:[1-9][0-9]*)\b
NONNEGINT :\b(?:[0-9]+)\b
WORD :\b\w+\b
NOTSPACE: \S+
SPACE: \s*
DATA: .*?
GREEDYDATA :.*
QUOTEDSTRING :(?>(?<!\\)(?>"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>(?>\\.|[^\\]+)+)|))
UUID :[A-Fa-f0-9]{8}-(?:[A-Fa-f0-9]{4}-){3}[A-Fa-f0-9]{12}
# URN, allowing use of RFC 2141 section 2.3 reserved characters
URN urn:[0-9A-Za-z][0-9A-Za-z-]{0,31}:(?:%[0-9a-fA-F]{2}|[0-9A-Za-z()+,.:=@;$_!*'/?#-])+

# Networking
MAC :(?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC})
CISCOMAC :(?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4})
WINDOWSMAC :(?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2})
COMMONMAC :(?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})
IPV6 :((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?
IPV4 :(?<![0-9])(?:(?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]))(?![0-9])
IP :(?:%{IPV6}|%{IPV4})
HOSTNAME :\b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(\.?|\b)
IPORHOST: (?:%{IP}|%{HOSTNAME})
HOSTPORT: %{IPORHOST}:%{POSINT}

# paths
PATH :(?:%{UNIXPATH}|%{WINPATH})
UNIXPATH :(/([\w_%!$@:.,+~-]+|\\.)*)+
TTY :(?:/dev/(pts|tty([pq])?)(\w+)?/?(?:[0-9]+))
WINPATH :(?>[A-Za-z]+:|\\)(?:\\[^\\?*]*)+
URIPROTO :[A-Za-z]([A-Za-z0-9+\-.]+)+
URIHOST :%{IPORHOST}(?::%{POSINT:port})?
# uripath comes loosely from RFC1738, but mostly from what Firefox
# doesn't turn into %XX
URIPATH: (?:/[A-Za-z0-9$.+!*'(){},~:;=@#%&_\-]*)+
#URIPARAM \?(?:[A-Za-z0-9]+(?:=(?:[^&]*))?(?:&(?:[A-Za-z0-9]+(?:=(?:[^&]*))?)?)*)?
URIPARAM \?[A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]<>]*
URIPATHPARAM :%{URIPATH}(?:%{URIPARAM})?
URI :%{URIPROTO}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATHPARAM})?

# Months: January, Feb, 3, 03, 12, December
MONTH :\b(?:[Jj]an(?:uary|uar)?|[Ff]eb(?:ruary|ruar)?|[Mm](?:a|ä)?r(?:ch|z)?|[Aa]pr(?:il)?|[Mm]a(?:y|i)?|[Jj]un(?:e|i)?|[Jj]ul(?:y)?|[Aa]ug(?:ust)?|[Ss]ep(?:tember)?|[Oo](?:c|k)?t(?:ober)?|[Nn]ov(?:ember)?|[Dd]e(?:c|z)(?:ember)?)\b
MONTHNUM :(?:0?[1-9]|1[0-2])
MONTHNUM2 :(?:0[1-9]|1[0-2])
MONTHDAY :(?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9])

# Days: Monday, Tue, Thu, etc...
DAY :(?:Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?)

# Years?
YEAR :(?>\d\d){1,2}
HOUR :(?:2[0123]|[01]?[0-9])
MINUTE: (?:[0-5][0-9])
# '60' is a leap second in most time standards and thus is valid.
SECOND :(?:(?:[0-5]?[0-9]|60)(?:[:.,][0-9]+)?)
TIME :(?!<[0-9])%{HOUR}:%{MINUTE}(?::%{SECOND})(?![0-9])
# datestamp is YYYY/MM/DD-HH:MM:SS.UUUU (or something like it)
DATE_US: %{MONTHNUM}[/-]%{MONTHDAY}[/-]%{YEAR}
DATE_EU :%{MONTHDAY}[./-]%{MONTHNUM}[./-]%{YEAR}
ISO8601_TIMEZONE: (?:Z|[+-]%{HOUR}(?::?%{MINUTE}))
ISO8601_SECOND: (?:%{SECOND}|60)
TIMESTAMP_ISO8601 :%{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?
DATE: %{DATE_US}|%{DATE_EU}
DATESTAMP %{DATE}[- ]%{TIME}
TZ: (?:[APMCE][SD]T|UTC)
DATESTAMP_RFC822 :%{DAY} %{MONTH} %{MONTHDAY} %{YEAR} %{TIME} %{TZ}
DATESTAMP_RFC2822: %{DAY}, %{MONTHDAY} %{MONTH} %{YEAR} %{TIME} %{ISO8601_TIMEZONE}
DATESTAMP_OTHER: %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{TZ} %{YEAR}
DATESTAMP_EVENTLOG :%{YEAR}%{MONTHNUM2}%{MONTHDAY}%{HOUR}%{MINUTE}%{SECOND}

# Syslog Dates: Month Day HH:MM:SS
SYSLOGTIMESTAMP: %{MONTH} +%{MONTHDAY} %{TIME}
PROG :[\x21-\x5a\x5c\x5e-\x7e]+
SYSLOGPROG :%{PROG:program}(?:\[%{POSINT:pid}\])?
SYSLOGHOST: %{IPORHOST}
SYSLOGFACILITY :<%{NONNEGINT:facility}.%{NONNEGINT:priority}>
HTTPDATE :%{MONTHDAY}/%{MONTH}/%{YEAR}:%{TIME} %{INT}

# Shortcuts
QS:%{QUOTEDSTRING}

# Log formats
SYSLOGBASE :%{SYSLOGTIMESTAMP:timestamp} (?:%{SYSLOGFACILITY} )?%{SYSLOGHOST:logsource} %{SYSLOGPROG}

# Log Levels
LOGLEVEL :([Aa]lert|ALERT|[Tt]race|TRACE|[Dd]ebug|DEBUG|[Nn]otice|NOTICE|[Ii]nfo|INFO|[Ww]arn?(?:ing)?|WARN?(?:ING)?|[Ee]rr?(?:or)?|ERR?(?:OR)?|[Cc]rit?(?:ical)?|CRIT?(?:ICAL)?|[Ff]atal|FATAL|[Ss]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?)


2.3自定义正则表达式调用

语法:(?<field_name>pattern)
举例:
message: 192.168.80.10 GET /index.html 15824 0.043

(?<remote_addr>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) (?<http_method>[A-Z]+) (?<request_uri>/.*) (?<response_bytes>[0-9]+) (?<response_time>[0-9\.]+)

  • 如果表达式匹配失败,会生成一个tags字段,字段值为 _grokparsefailure,需要重新检查上边的match配置解析是否正确。

在这里插入图片描述

举例:192.168.243.3 - - [11/Jul/2023:18:00:50 +0800] “GET /noindex/css/fonts/Bold/OpenSans-Bold.ttf HTTP/1.1” 404 238 “http://192.168.243.104/noindex/css/open-sans.css” "Mozilla/5.0 (Windows NT 10.0; Win64; x64;

在这里插入图片描述
在这里插入图片描述

三、mutate 数据修改插件

  • 它提供了丰富的基础类型数据处理能力。可以重命名,删除,替换和修改事件中的字段。

3.1 Mutate 过滤器常用的配置选项

命令解释
add_field向事件添加新字段,也可以添加多个字段
remove_field从事件中删除任意字段
add_tag向事件添加任意标签,在tag字段中添加一段自定义的内容,当tag字段中超过一个内容的时候会变成数组
remove_tag从事件中删除标签(如果存在)
convert将字段值转换为另一种数据类型
id向现场事件添加唯一的ID
lowercase将字符串字段转换为其小写形式
replace用新值替换字段
strip删除开头和结尾的空格
uppercase将字符串字段转换为等效的大写字母
update用新值更新现有字段
rename重命名事件中的字段
gsub通过正则表达式替换字段中匹配到的值
merge合并数组或 hash 事件
split通过指定的分隔符分割字段中的字符串为数组

3.2示例

将字段message重命名为new_message

filter {
    mutate {
	    #写法1,使用中括号括起来
        rename => ["message" => "new_message"]

        #写法2,使用大括号{}括起来
	    rename => { "message" => "new_message" }		
    }
}

在这里插入图片描述

在这里插入图片描述
添加字段

filter {
    mutate {
        add_field => {
        	"f1" => "field1"
        	"f2" => "field2"
        }
    }
}

在这里插入图片描述

在这里插入图片描述

将字段删除

filter {
    mutate {
        remove_field  =>  ["message", "@version", "tags"]
    }
}

将filedName1字段数据类型转换成string类型,filedName2字段数据类型转换成float类型

filter {
    mutate {
        #写法1,使用中括号括起来
        convert  =>  ["filedName1", "string"]
		
        #写法2,使用大括号{}括起来
		convert => { "filedName2" => "float" }
    }
}

将filedName字段中所有"/“字符替换为”_"

filter {
    mutate {
        gsub => ["filedName", "/" , "_"]
    }
}

将filedName字段中所有",“字符后面添加空格

filter {
    mutate {
        gsub => ["filedName", "," , ", "]
    }
}

将filedName字段以"|"为分割符拆分数据成为数组

filter {
    mutate {
        split => ["filedName", "|"]
    }
}

合并 “filedName1” 和 “ filedName2” 两个字段

filter {
    merge  { "filedName2" => "filedName1" }
}

用新值替换filedName字段的值

filter {
    mutate {
        replace => { "filedName" => "new_value" }
    }
}

添加字段first,值为message数组的第一个元素的值

filter {
    mutate {
        split => ["message", "|"]
        add_field => {
            "first" => "%{[message][0]}"    
        } 
    }
}

有条件的添加标签

filter {
    #在日志文件路径包含 access 的条件下添加标签内容
    if [path] =~ "access" {
        mutate {
            add_tag => ["Nginx Access Log"]
        }
    }
    
    #在日志文件路径是 /var/log/nginx/error.log 的条件下添加标签内容
    if [path] == "/var/log/nginx/error.log" {
        mutate {
            add_tag => ["Nginx Error Log"]
        }
    }
}

四、multiline多行合并插件

  • java错误日志一般都是一条日志很多行的,会把堆栈信息打印出来,当经过 logstash 解析后,每一行都会当做一条记录存放到 ES, 那这种情况肯定是需要处理的。 这里就需要使用 multiline 插件,对属于同一个条日志的记录进行拼接。

4.1安装multiline插件

在线安装插件

cd /usr/share/logstash
bin/logstash-plugin install logstash-filter-multiline

离线安装插件

  • 先在有网的机器上在线安装插件,然后打包,拷贝到服务器,执行安装命令
bin/logstash-plugin prepare-offline-pack --overwrite --output logstash-filter-multiline.zip logstash-filter-multiline

bin/logstash-plugin install file:///usr/share/logstash/logstash-filter-multiline.zip

在这里插入图片描述

检查下插件是否安装成功,可以执行以下命令查看插件列表

bin/logstash-plugin list

在这里插入图片描述

4.2使用multiline插件

第一步:每一条日志的第一行开头都是一个时间,可以用时间的正则表达式匹配到第一行。
第二步:然后将后面每一行的日志与第一行合并。
第三步:当遇到某一行的开头是可以匹配正则表达式的时间的,就停止第一条日志的合并,开始合并第二条日志。
第四步:重复第二步和第三步。

filter {
  multiline {
    pattern => "^\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}.\d{3}"
    negate => true
    what => "previous"
  }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • pattern:用来匹配文本的表达式,也可以是grok表达式
  • what:如果pattern匹配成功的话,那么匹配行是归属于上一个事件,还是归属于下一个事件。previous: 归属于上一个事件,向上合并。next: 归属于下一个事件,向下合并
  • negate:是否对pattern的结果取反。false:不取反,是默认值。true:取反。将多行事件扫描过程中的行匹配逻辑取反(如果pattern匹配失败,则认为当前行是多行事件的组成部分)

五、date 时间处理插件

  • 用于分析字段中的日期,然后使用该日期或时间戳作为事件的logstash时间戳
  • 在Logstash产生了一个Event对象的时候,会给该Event设置一个时间,字段为“@timestamp”,同时,我们的日志内容一般也会有时间,但是这两个时间是不一样的,因为日志内容的时间是该日志打印出来的时间,而“@timestamp”字段的时间是input插件接收到了一条数据并创建Event的时间,所有一般来说的话“@timestamp”的时间要比日志内容的时间晚一点,因为Logstash监控数据变化,数据输入,创建Event导致的时间延迟。这两个时间都可以使用,具体要根据自己的需求来定。
filter {
    date {
        match => ["access_time", "dd/MMM/YYYY:HH:mm:ss Z", "UNIX", "yyyy-MM-dd HH:mm:ss", "dd-MMM-yyyy HH:mm:ss"]
		target => "@timestamp"
		#指定时区为亚洲伤害
		timezone => "Asia/Shanghai"
    } 
}

在这里插入图片描述
在这里插入图片描述

  • match:用于配置具体的匹配内容规则,前半部分内容表示匹配实际日志当中的时间戳的名称,后半部分则用于匹配实际日志当中的时间戳格式,这个地方是整条配置的核心内容,如果此处规则匹配是无效的,则生成后的日志时间戳将会被input插件读取的时间替代。
    如果时间格式匹配失败,会生成一个tags字段,字段值为 _dateparsefailure,需要重新检查上边的match配置解析是否正确。
  • target:将匹配的时间戳存储到给定的目标字段中。如果未提供,则默认更新事件的@timestamp字段。
  • timezone:当需要配置的date里面没有时区信息,而且不是UTC时间,需要设置timezone参数。

5.1时间戳详解

yyyy #全年号码。 例如:2015。
yy #两位数年份。 例如:2015年的15。

M #最小数字月份。 例如:1 for January and 12 for December.。
MM #两位数月份。 如果需要,填充零。 例如:01 for January and 12 for Decembe
MMM #缩短的月份文本。 例如: Jan for January。 注意:使用的语言取决于您的语言环境。 请参阅区域设置以了解如何更改语言。
MMMM #全月文本,例如:January。 注意:使用的语言取决于您的语言环境。

d #最少数字的一天。 例如:1月份的第一天1。
dd #两位数的日子,如果需要的话可以填零.例如:01 for the 1st of the month。

H #最小数字小时。 例如:0表示午夜。
HH #两位数小时,如果需要填零。 例如:午夜00。

m #最小的数字分钟。 例如:0。
mm #两位数分钟,如果需要填零。 例如:00。

s #最小数字秒。 例如:0。
ss #两位数字,如果需要填零。 例如:00。

毫秒( 秒的小数部分最大精度是毫秒(SSS)。除此之外,零附加。)

S #十分之一秒。例如:0为亚秒值012
SS #百分之一秒 例如:01为亚秒值01
SSS #千分之一秒 例如:012为亚秒值012

时区偏移或身份

Z #时区偏移,结构为HHmm(Zulu/UTC的小时和分钟偏移量)。例如:-0700。
ZZ #时区偏移结构为HH:mm(小时偏移和分钟偏移之间的冒号)。 例如:-07:00。
ZZZ #时区身份。例如:America/Los_Angeles。 注意:有效的ID在列表中列出http://joda-time.sourceforge.net/timezones.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/742550.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

操作系统——输入输出IO管理

文章目录 **1 I/O管理概述****1.1 I/O设备****1.2 I/O控制方式****1.2.1 程序直接控制方式****1.2.2 中断驱动方式****1.2.3 DMA方式****1.2.4 通道控制方式** **1.3 I/O软件层次结构****1.4 应用程序I/O接口** **2 设备独立性软件****2.1 高速缓冲与缓冲区****2.2 设备分配和回…

车牌识别--http协议

文章目录 libcurl车牌识别 前言 基于https协议访问网址实现车牌识别 http是超文本传输协议&#xff0c;它可以在B/S模式下解决tcp传输格式的问题&#xff0c;处于tcp之上在应用层 https是http加密版本&#xff0c;通过httpssl实现加密版http 我们车牌识别通过http协议调用翔云…

Django_admin数据管理后台

目录 一、基础操作 二、自定义后台操作数据行为 源码等资料获取方法 admin数据管理后台是django内置的一个后台管理界面&#xff0c;能查看已注册模型类的数据结构&#xff0c;以及对数据的增删改。 一、基础操作 1.1 检查项目目录下的urls.py有没有如下配置 1.2 创建djan…

使用U盘在无系统的机器上安装Ubuntu

1、在Bios中选择将USB 作为Boot Option #1 2、插入制作好的系统盘&#xff08;系统盘制作可以看上一篇博客&#xff09; 3、save & exit选择 save change and reset 4、 开始安装系统 如果出现安装窗口过大无法点击下一步&#xff0c;可以使用ALTF7拖动窗口。

java中的BIO NIO AIO

多路复用IO模型是目前使用的比较多的模型。java中的NIO常用的理解是在 网络IO中&#xff0c;那么在网络IO中为什么NIO比BIO效率更高&#xff1f;我们的web项目中是用的哪种呢&#xff1f;可以往下看。 JavaNIO实际上就是多路复用IO。在多路复用IO模型中&#xff0c;会有一个线程…

【Unity】Unity2022设置2D动画的sample

首先在主页面选择Animation 出现这样的一个框 点击红点行&#xff0c;最右侧的三个点 将Show Sample Rate勾选上即可

Fiddler工具 — Fiddler常用插件(Willow)

Fiddler已有的功能已经够我们日常工作中使用了&#xff0c;为了更好的扩展Fiddler&#xff0c;Fiddler也是支持一些插件的安装&#xff0c;也支持用户自己开发插件并安装。 Fiddler插件下载地址&#xff1a;https://www.telerik.com/fiddler/add-ons 1、Traific Difer插件 Tr…

【Java】Map(包括HashMap)

Map HashMap 和 Hashtable 的区别HashMap 和 HashSet 区别HashMap 的底层实现JDK1.8 之前JDK1.8红黑树 HashMap 的长度为什么是 2 的幂次方HashMap 多线程操作导致死循环问题HashMap 为什么线程不安全&#xff1f; ConcurrentHashMapConcurrentHashMap 和 Hashtable 的区别JDK …

常见面试题之JVM实践(调优)

1. JVM调优的参数可以在哪里设置参数值&#xff1f; 1.1 tomcat的设置vm参数 修改TOMCAT_HOME/bin/catalina.sh文件&#xff0c;如下图&#xff1a; JAVA_OPTS"-Xms512m -Xmx1024m" 1.2 springboot项目jar文件启动 通常在linux系统下直接加参数启动springboot项…

在Pandas中处理缺失数据

当没有为一个或多个项目或整个单元提供信息时&#xff0c;可能会出现数据缺失。缺失数据在现实生活中是一个非常大的问题。缺失数据在pandas中也可以称为NA&#xff08;不可用&#xff09;值。在DataFrame中&#xff0c;有时许多数据集只是缺少数据&#xff0c;因为它存在而未被…

52 # 二叉树的前中后遍历

二叉树的遍历 线性数据结构遍历比较简单&#xff0c;可以采用正序遍历、逆序遍历。 遍历树的目的一般是修改树&#xff0c;比如修改树的节点&#xff0c;采用访问者模式 前序遍历 前序遍历&#xff08;preorder traversal&#xff09;&#xff1a;先访问根节点&#xff0c;…

Go语言struct要使用 tags的原因解析

这篇文章主要介绍了为什么 Go 语言 struct 要使用 tags,在本文中&#xff0c;我们将探讨为什么 Go 语言中需要使用 struct tags&#xff0c;以及 struct tags 的使用场景和优势&#xff0c;需要的朋友可以参考下 在 Go 语言中&#xff0c;struct 是一种常见的数据类型&#xf…

由于找不到vcomp100.dll,无法继续执行代码,解决方法

为什么会由于找不到vcomp100.dll,无法继续执行代码问题呢&#xff1f; 文件被误删除&#xff1a;有时候&#xff0c;在进行系统清理或卸载应用程序时&#xff0c;可能会不小心删除了vcomp100.dll文件。如果某个程序依赖于该文件&#xff0c;并且文件被删除&#xff0c;那么该程…

ESP32开发:IDFV4.4配置LVGL8.3

配置LVGL8.3源码 LVGL GITHUB代码仓库如下&#xff1a;https://github.com/lvgl/lvgl/tree/release/v8.3 官方已经在ESP32上移植好的代码demo&#xff0c;目前最新版是LVGL 7.9&#xff1a;https://github.com/lvgl/lv_port_esp32 我们可以将LVGL官方配置好的ESP32 LVGL仓库下…

超详细的学习笔记:CSS盒子模型(附代码示例)

目录 一、CSS三大特性 1、继承性 2、层叠性 3、优先级 4、权重叠加的计算 二、PxCook的基本使用 三、盒子模型 1、盒子模型的介绍 2、内容的宽度和高度 3、边框 (border) 1、连写形式 2、单方向设置 3、单个属性 8、内边距&#xff08;padding&#xff09;和外边…

arm学习stm32之spi总线数码管倒计时

由于时间没有用时间计时器操作&#xff0c;有些误差&#xff0c;后续有空会翻新计时器版本 main.c #include "spi.h" extern void printf(const char *fmt, ...); void delay_ms(int ms) {int i,j;for(i 0; i < ms;i)for (j 0; j < 1800; j); } int num[10…

钉钉提示 redirect_url的域名不在appid的安全域名内

钉钉提示 redirect_url的域名不在appid的安全域名内 1、需要在《钉钉开放平台》- 开发者后台设置《钉钉扫码登陆功能》 2、如果钉钉界面没有钉钉扫码登陆功能-》点击浏览器右下角-》《返回旧版》 3、备注&#xff1a;当前访问的IP地址跟钉钉扫码登陆功能填写的IP地址需保持一致…

代码审计工具Fortify基本使用

最近接触到一款代码审计的工具 — Fortify SCA and Applications 22.2.0&#xff0c;现就其基本使用做一简单介绍&#xff01; Fortify是一个应用安全测试软件&#xff0c;是Micro Focus旗下AST&#xff08;应用程序安全测试&#xff09;产品。 Fortify能够提供静态和动态应用…

Acwing 853.有边数限制的最短路

Acwing 853.有边数限制的最短路 链接:853. 有边数限制的最短路 - AcWing题库 /* 题解:bellman_ford算法 可以算是一种暴力的算法了 他可以解决有复权边的单源最短路径 也可以解决图是否存在负环的问题 还可以求出 不超过k条边的最短路径问题 但是效率低下 时间复杂度为o(nk)n…

超有趣的linux命令2

超有趣的linux命令2 此次实验命令均在Ubuntu16.04版本上测试 注意有些命令需要在图形化界面才能显示效果 温馨提示&#xff1a;可能有人是第一次接触Ubuntu&#xff0c;所以下面详细写了如何配置源和网络&#xff0c;以及安装命令的方式 1. 首先配置软件源 以命令行方式配置…