生活指南——让生活变得更简单

tail定位时间的简单介绍

课程:

Linux系统日志怎么查看

1. 前言

在Linux日常管理中,我们肯定有查看某些服务的日志需求,或者是系统本身的日志。本文主要介绍如何查看Linux的系统日志,包括文件的路径、工具的使用等等。会看Linux日志是非常重要的,不仅在日常操作中可以迅速排错,也可以快速的定位。

2. 如何查看Linux日志

Linux日志文件的路径一般位于,/var/log/,比如ngix的日志路径为/var/log/nginx/,如果要查看某服务的日志,还可以使用systemctl status xxx,比如查看ssh服务的壮态,systemctl status sshd

查看Linux某服务的日志

Liunx的配置文件在/etc/rsyslog.d里,可以看到如下信息

在linux系统当中,有三个主要的日志子系统:

1、连接时间日志:由多个程序执行,把记录写入到/var/log/wtmp和/var/run/utmp,

login等程序会更新wtmp和utmp文件,使系统管理员能够跟踪谁在何时登录到系统。

2、进程统计:由系统内核执行,当一个进程终止时,为每个进程往进程统计文件中写一个记录。进程统计的目的是为系统中的基本服务提供命令使用统计

3、错误日志:由rsyslogd守护程序执行,各种系统守护进程、用户程序和内核通过rsyslogd守护程序向文件/var/log/messages报告值得注意的时间。另外有许多linux程序创建日志,像HTTP和FTP这样提供的服务器也保持详细的日志。

4、其他日志……

查看Linux日志默认路径

可以看到在/var/log目录下存在很多的日志文件,接下来就对里面的一些常用日志文件进行分析

主要日志文件介绍:

内核及公共消息日志:/var/log/messages

计划任务日志:/var/log/cron

系统引导日志:/var/log/dmesg

邮件系统日志:/var/log/maillog

用户登录日志:/var/log/lastlog

/var/log/boot.log(记录系统在引导过程中发生的时间)

/var/log/secure (用户验证相关的安全性事件)

/var/log/wtmp(当前登录用户详细信息)

/var/log/btmp(记录失败的的记录)

/var/run/utmp(用户登录、注销及系统开、关等事件)

日志文件详细介绍:

/var/log/secure

Linux系统安全日志,记录用户和工作组的情况、用户登陆认证情况

例子:我创建了一个zcwyou的用户,然后改变了该用户的密码,于是该信息就被记录到该日志下

Linux系统安全日志默认路径

该日志就详细的记录了我操作的过程。

内核及公共信息日志,是许多进程日志文件的汇总,从该文件中可以看出系统任何变化

查看Linux内核及公共信息日志

系统引导日志

该日志使用dmesg命令快速查看最后一次系统引导的引导日志

查看Linux系统系统引导日志

最近的用户登录事件,一般记录最后一次的登录事件

该日志不能用诸如cat、tail等查看,因为该日志里面是二进制文件,可以用lastlog命令查看,它根据UID排序显示登录名、端口号(tty)和上次登录时间。如果一个用户从未登录过,lastlog显示 Never logged。

该日志文件永久记录每个用户登录、注销及系统的启动、停机的事件。该日志为二进制文件,不能用诸如tail/cat/等命令,使用last命令查看。

记录邮件的收发

此文件是记录错误登录的日志,可以记录有人使用暴力破解ssh服务的日志。该文件用lastb打开

该日志记录当前用户登录的情况,不会永久保存记录。可以用who/w命令来查看

3. 常用的日志分析工具与使用方法

3.1 统计一个文本中包含字符个数

3.2 查看当天访问排行前10的url

3.3 查看apache的进程数

3.4 访问量前10的IP

cut部分表示取第1列即IP列,取第4列则为URL的访问量

3.5 查看最耗时的页面

按第2列响应时间逆序排序

3.6 使用grep查找文件中指定字符出现的次数

-o 指示grep显示所有匹配的地方,并且每一个匹配单独一行输出。这样只要统计输出的行数就可以知道这个字符出现的次数了。

4. 总结

查看Linux日志需求了解和熟悉使用一些常用的工具方能提升我们的查找和定位效率。比如使用 Grep 搜索,使用Tail命令,使用Cut,使用AWK 和 Grok 解析日志和使用 Rsyslog 和 AWK 过滤等等,只要能掌握这些工具。我们才能高效地处理和定位故障点。

java 什么情况下使用 并发队列

并发队列是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。它采用了“wait-free”算法来实现,该算法在Michael

Scott算法上进行了一些修改。

入队列

入队列就是将入队节点添加到队列的尾部。为了方便理解入队时队列的变化,以及head节点和tair节点的变化,每添加一个节点我就做了一个队列的快照图。

第一步添加元素1。队列更新head节点的next节点为元素1节点。又因为tail节点默认情况下等于head节点,所以它们的next节点都指向元素1节点。

第二步添加元素2。队列首先设置元素1节点的next节点为元素2节点,然后更新tail节点指向元素2节点。

第三步添加元素3,设置tail节点的next节点为元素3节点。

第四步添加元素4,设置元素3的next节点为元素4节点,然后将tail节点指向元素4节点。

通过debug入队过程并观察head节点和tail节点的变化,发现入队主要做两件事情,

第一是将入队节点设置成当前队列尾节点的下一个节点。

第二是更新tail节点,如果tail节点的next节点不为空,则将入队节点设置成tail节点,如果tail节点的next节点为空,则将入队节点设置成tail的next节点,所以tail节点不总是尾节点,理解这一点对于我们研究源码会非常有帮助。

上面的分析让我们从单线程入队的角度来理解入队过程,但是多个线程同时进行入队情况就变得更加复杂,因为可能会出现其他线程插队的情况。如果有一个线程正在入队,那么它必须先获取尾节点,然后设置尾节点的下一个节点为入队节点,但这时可能有另外一个线程插队了,那么队列的尾节点就会发生变化,这时当前线程要暂停入队操作,然后重新获取尾节点。让我们再通过源码来详细分析下它是如何使用CAS算法来入队的。

public boolean offer(E e) {    

          

   if (e == null) throw new NullPointerException();    

         

    //入队前,创建一个入队节点    

         

    Node/ee n = new Node/ee(e);    

  

   retry:    

          

    //死循环,入队不成功反复入队。    

          

    for (;;) {    

           

        //创建一个指向tail节点的引用    

           

       Node/ee t = tail;    

           

     //p用来表示队列的尾节点,默认情况下等于tail节点。    

           

      Node/ee p = t;    

           

      for (int hops = 0; ; hops++) {    

           

     //获得p节点的下一个节点。    

           

        Node/ee next = succ(p);    

           

     //next节点不为空,说明p不是尾节点,需要更新p后在将它指向next节点    

           

        if (next != null) {    

           

     //循环了两次及其以上,并且当前节点还是不等于尾节点    

           

        if (hops  HOPS  t != tail)    

           

            continue retry;    

           

            p = next;    

           

        }    

           

     //如果p是尾节点,则设置p节点的next节点为入队节点。    

           

         else if (p.casNext(null, n)) {    

           

        //如果tail节点有大于等于1个next节点,则将入队节点设置成tair节点,更新失败了也没关系,因为失败了表示有其他线程成功更新了tair节点。    

           

    if (hops = HOPS)    

           

           casTail(t, n); // 更新tail节点,允许失败    

           

        return true;    

           

         }    

           

        // p有next节点,表示p的next节点是尾节点,则重新设置p节点    

           

        else {    

           

          p = succ(p);    

           

        }    

           

     }    

         

  }    

          

}

从源代码角度来看整个入队过程主要做二件事情。

第一步定位尾节点。tail节点并不总是尾节点,所以每次入队都必须先通过tail节点来找到尾节点,尾节点可能就是tail节点,也可能是tail节点的next节点。代码中循环体中的第一个if就是判断tail是否有next节点,有则表示next节点可能是尾节点。获取tail节点的next节点需要注意的是p节点等于p的next节点的情况,只有一种可能就是p节点和p的next节点都等于空,表示这个队列刚初始化,正准备添加第一次节点,所以需要返回head节点。获取p节点的next节点代码如下

final Node/ee succ(Node/ee p) {    

        

     Node/ee next = p.getNext();    

 

       return (p == next) ? head : next;    

        

      }

第二步设置入队节点为尾节点。p.casNext(null, n)方法用于将入队节点设置为当前队列尾节点的next节点,p如果是null表示p是当前队列的尾节点,如果不为null表示有其他线程更新了尾节点,则需要重新获取当前队列的尾节点。

hops的设计意图。上面分析过对于先进先出的队列入队所要做的事情就是将入队节点设置成尾节点,doug lea写的代码和逻辑还是稍微有点复杂。那么我用以下方式来实现行不行?

public boolean offer(E e) {    

      

    if (e == null)    

           

       throw new NullPointerException();    

          

      Node/ee n = new Node/ee(e);    

          

          for (;;) {    

          

      Node/ee t = tail;    

         

       if (t.casNext(null, n)  casTail(t, n)) {    

          

             return true;    

          

     }    

         

     }    

         

}

让tail节点永远作为队列的尾节点,这样实现代码量非常少,而且逻辑非常清楚和易懂。但是这么做有个缺点就是每次都需要使用循环CAS更新tail节点。如果能减少CAS更新tail节点的次数,就能提高入队的效率,所以doug

lea使用hops变量来控制并减少tail节点的更新频率,并不是每次节点入队后都将 tail节点更新成尾节点,而是当

tail节点和尾节点的距离大于等于常量HOPS的值(默认等于1)时才更新tail节点,tail和尾节点的距离越长使用CAS更新tail节点的次数就会越少,但是距离越长带来的负面效果就是每次入队时定位尾节点的时间就越长,因为循环体需要多循环一次来定位出尾节点,但是这样仍然能提高入队的效率,因为从本质上来看它通过增加对volatile变量的读操作来减少了对volatile变量的写操作,而对volatile变量的写操作开销要远远大于读操作,所以入队效率会有所提升。

 private static final int HOPS = 1;

还有一点需要注意的是入队方法永远返回true,所以不要通过返回值判断入队是否成功。

4. 出队列

出队列的就是从队列里返回一个节点元素,并清空该节点对元素的引用。让我们通过每个节点出队的快照来观察下head节点的变化。

从上图可知,并不是每次出队时都更新head节点,当head节点里有元素时,直接弹出head节点里的元素,而不会更新head节点。只有当head节点里没有元素时,出队操作才会更新head节点。这种做法也是通过hops变量来减少使用CAS更新head节点的消耗,从而提高出队效率。让我们再通过源码来深入分析下出队过程。

 public E poll() {    

        

    Node/ee h = head;    

       

    // p表示头节点,需要出队的节点    

        

      Node/ee p = h;    

        

      for (int hops = 0;; hops++) {    

        

         // 获取p节点的元素    

        

         E item = p.getItem();    

        

         // 如果p节点的元素不为空,使用CAS设置p节点引用的元素为null,如果成功则返回p节点的元素。    

        

         if (item != null  p.casItem(item, null)) {    

         

         if (hops = HOPS) {    

        

              //将p节点下一个节点设置成head节点    

        

              Node/ee q = p.getNext();    

        

              updateHead(h, (q != null) ? q : p);    

       

              }    

        

                  return item;    

 

              }    

        

        // 如果头节点的元素为空或头节点发生了变化,这说明头节点已经被另外一个线程修改了。那么获取p节点的下一个节点    

        

        Node/ee next = succ(p);    

        

        // 如果p的下一个节点也为空,说明这个队列已经空了    

       

        if (next == null) {    

        

       // 更新头节点。    

         

             updateHead(h, p);    

        

             break;    

         

             }    

        

      // 如果下一个元素不为空,则将头节点的下一个节点设置成头节点    

         

       p = next;    

         

      }    

        

          return null;    

        

      }

首先获取头节点的元素,然后判断头节点元素是否为空,如果为空,表示另外一个线程已经进行了一次出队操作将该节点的元素取走,如果不为空,则使用CAS的方式将头节点的引用设置成null,如果CAS成功,则直接返回头节点的元素,如果不成功,表示另外一个线程已经进行了一次出队操作更新了head节点,导致元素发生了变化,需要重新获取头节点。

泰拉瑞亚怎么锁定时间?

首先准备工具,烧饼修改器。

1、打开烧饼,进入游戏,烧饼设置为模糊搜索数据类型是DW类型

2、直接搜索。

3、不断的搜索变大了,直到剩余数据少于1000,搜索过程中不能出现昼夜交替。

4、数据少于1000后把筛选方式改为范围筛选(1000000000null无限大)

5、筛选完后大约还有100+数据,找到其中一个地址为5****d24的地址,其余的全部删掉

6、之前找到的地址就是昼夜时间了,偏移-4(时间流速)添加到列表,偏移4(各种天气,月亮0,太阳1,日食257,血月65536,南瓜月16777216)添加到列表。这个是修改时间流速的结果,顺便说下修改出的南瓜月只能刷新出稻草人。

7、时间可以锁定,可以用烧饼锁定或修改时间流速为0,把搜索到的那个数值锁定就好了,重新进游戏的话,时间会从上次退出游戏的时间开始流逝。各种天气还有很多对应数据,比如还有-65535是血月,-1、-2是日食。

泰拉瑞亚如何修改时间 安卓版时间修改教程:

在LINUX的命令提示符及CMD命令提示符中显示时间

在linux的命令提示符及CMD命令提示符中显示时间用途之一是可以查看某个命令或程序的执行时间。一、CMD中显示时间设置参数说明:$P:当前路径$G:(大于号)$T:当前时间,精确到0.01s实验如下:C:/Users/g4-1016txprompt

$P$S$T$GC:/Users/g4-1016tx

13:19:53.92arp

-a接口:

192.168.0.189

---

0xb

Internet

地址

物理地址

类型

192.168.0.1

c8-3a-35-5a-f1-10

动态C:/Users/g4-1016tx

13:19:56.46二、修改linux中shell命令提示符显示1.修改单个用户的提示在用户环境变量中增加这一项即可,这种只修改当前用户的提示符。注意修改后需要重新加载用户环境

变量source

.bash_profile

或者退出重新登陆。[oracle@dg2:~Sat

Aug

03-13:09:57$]

tail

-n

1

.bash_profileexport

PS1='

[/u@/h:/w/d-/t/$]

'2.修改全局用户提示符如果需要修改整个系统所以用户的提示,需要修改/etc/bashrc

在里面增加的同样是下面这一句。[root@dg2

~]#

tail

-n

1

/etc/profileexport

PS1='

[/u@/h:/w/d-/t/$]

'[root@dg2

~]#

su

-

oracle[oracle@dg2:~Sat

Aug

03-13:16:59$]命令提示符中各个显示参数的详细解释:即可,其中/u显示当前用户账号,/h显示当前主机名,/W显示当前路径,/$显示'$'符号/W

代替

/w

就可以实现绝对路径到相对路径的转换/d

:代表日期,格式为weekday

month

date,例如:Mon

Aug

1/H

:完整的主机名称。例如:我的机器名称为:fc4.linux,则这个名称就是fc4.linux/h

:仅取主机的第一个名字,如上例,则为fc4,.linux则被省略/t

:显示时间为24小时格式,如:HH:MM:SS/T

:显示时间为12小时格式/A

:显示时间为24小时格式:HH:MM/u

:当前用户的账号名称/v

:BASH的版本信息/w

:完整的工作目录名称。家目录会以

~代替/W

:利用basename取得工作目录名称,所以只会列出最后一个目录/#

:下达的第几个命令/$

:提示字符,如果是root时,提示符为:#

,普通用户则为:$三、直接在类UNIX中使用TIME命令统计命令运行时间使用方法是在需要执行的命令前加上time比如:[oracle@bys001

~]$

time

dateMon

Sep

16

17:00:31

CST

2013real

0m0.015suser

0m0.001ssys

0m0.013s[oracle@bys001

~]$

time

echo

hellohelloreal

0m0.000suser

0m0.000ssys

0m0.001s

  • 评论列表:
  •  访客
     发布于 2022-09-03 18:11:06  回复该评论
  • 操作来减少了对volatile变量的写操作,而对volatile变量的写操作开销要远远大于读操作,所以入队效率会有所提升。 private static final int HOPS = 1;还有一点需要注意的是入队方法永远返
  •  访客
     发布于 2022-09-04 02:11:47  回复该评论
  •             }                              return item;                   }                    // 如果头节点的元素为空或头节点发生了变化,这说明头节点已经被

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Copyright Your WebSite.Some Rights Reserved.