redis-aux 正在参加 2020 年度 OSC 中国开源项目评选,请投票支持!
redis-aux 在 2020 年度 OSC 中国开源项目评选 中已获得 {{ projectVoteCount }} 票,请投票支持!
投票让它出道
已投票
redis-aux 获得 2020 年度 OSC 中国开源项目评选「最佳人气项目」 !
redis-aux 获得 2020 年度 OSC 中国开源项目评选「最佳人气项目」「最积极运营项目」 !
redis-aux 获得 2020 年度 OSC 中国开源项目评选「最积极运营项目」 !
授权协议 AFL-3.0
开发语言 Java Lua
操作系统 跨平台
软件类型 开源软件
所属分类 程序开发常用工具包
开源组织
地区 国产
提 交 者 1016644172
适用人群 未知
收录时间 2020-01-06

软件简介

这篇文章主要是介绍功能点,先看看这个工具包有什么可以用的,目前主要有两个模块——布隆过滤器、基于注解限流。基于redisTemplate

  • 用法

这里用maven作为工具管理包演示,添加jitpack源、添加下面的依赖

    <repositories>
        <repository>
            <id>jitpack.io</id>
            <url>https://jitpack.io</url>
        </repository>
     </repositories>
<dependency>
	    <groupId>com.github.97lele</groupId>
	    <artifactId>redis-aux</artifactId>
	    <version>0.3.8</version>
	</dependency>
  • 布隆过滤器演示

在启动类上添加启用布隆过滤器的注解

@EnableBloomFilter(bloomFilterPath = "com.example.demo")

2个属性,分别为

1.需要支持lambda表达式添加的实体路径

2.是否开启支持@Trancational注解,需要和数据库事务配合使用

配置好redis

spring:
 redis:
   port: 6379
   host: 127.0.0.1
  • 添加方法

只有两种,一种是通过构建操作对象来添加,一种是通过解析lambda表达,获取其字段上的注解信息来添加

若要调用SFunction为参数的方法需要在EnableBloomFilter配置扫描路径

主要是exceptedInsertions,fpp,timeOut,local 这里四个参数,分别为预计插入的个数,允许的错误率,过期时间,是否为本地

演示,添加主要分为普通添加

@Test
   public void simpleTest() {
        boolean isLocal=true;
        String key = "testAdd";
        //默认local为false
        AddCondition addCondition = AddCondition.create().keyName(key).local(isLocal);
        BaseCondition baseCondition = addCondition.toBaseCondition();
        bloomFilter.add(addCondition, "hello");
        System.out.println("contain he:"+bloomFilter.mightContain(baseCondition,"he"));
        System.out.println("contain hello:"+bloomFilter.mightContain(baseCondition,"hello"));
        //多值操作
        bloomFilter.addAll(addCondition,Arrays.asList("h","a","c"));
        System.out.println("before reset:"+bloomFilter.mightContains(baseCondition,Arrays.asList("a","b","c")));
        //重置
        bloomFilter.reset(baseCondition);
        System.out.println("after reset:"+bloomFilter.mightContains(baseCondition,Arrays.asList("a","hello","qq")));
        System.out.println("before delete:"+bloomFilter.containKey(baseCondition));
        //删除
        bloomFilter.remove(baseCondition);
        System.out.println("after delete:"+bloomFilter.containKey(baseCondition));
    }

结果

lambda演示

需要实体类实现getter,并且添加上前缀名,否则默认为类名,需要操作的属性上面添加BloomFilterProperty注解,该注解可填充属性有以下,key如果不填按字段名处理,另外要在enableBloomFilter的注解里填写扫描路径

double fpp() default 0.03;

    long exceptionInsert() default 1000;

    String key() default "";

    long timeout() default -1L;

    TimeUnit timeUnit() default TimeUnit.SECONDS;
    
    boolean local() default false;

 

@BloomFilterPrefix
public class TestEntity {
    @BloomFilterProperty(enableGrow = true,exceptionInsert = 5,timeout = 30)
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

基于lambda的测试代码

@Test
    public void lambdaTest() throws InterruptedException {
      bloomFilter.addAll(TestEntity::getName, Arrays.asList(13, 14, 15, 16));
        System.out.println(bloomFilter.mightContain(TestEntity::getName, 15));
        System.out.println(bloomFilter.mightContains(TestEntity::getName, Arrays.asList(13, 200)));
    }

结果

键过期测试

 @Test
    void timeOutTest() {
          boolean isLocal=true;
        bloomFilter.add(AddCondition.create().keyName("a1").timeout(30L).timeUnit(TimeUnit.SECONDS).local(isLocal), 1);
        bloomFilter.addAll(AddCondition.create().keyName("a4").timeUnit(TimeUnit.SECONDS).timeout(10L).local(isLocal), Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9));
        bloomFilter.add(AddCondition.create().keyName("a2").timeout(11L).timeUnit(TimeUnit.SECONDS).local(isLocal), 1);
        bloomFilter.add(AddCondition.create().keyName("a3").timeout(22L).timeUnit(TimeUnit.SECONDS).local(isLocal), 1);
        System.out.println(bloomFilter.mightContain(BaseCondition.create().keyName("a1"), 1));
        try {
            TimeUnit.SECONDS.sleep(35L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(bloomFilter.containKey(BaseCondition.create().keyName("a1")));
    }

结果

开启支持事务

清空redis的键

service代码,一个有错,一个无错

package com.example.demo.service;

import com.example.demo.dao.UserTicketMapper;
import com.example.demo.entity.UserTicket;
import com.trendy.util.redis.aux.bloomfilter.autoconfigure.RedisBloomFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * @author: lele
 * @date: 2020/1/4 下午11:51
 */
@Service
public class TestService {

    @Autowired
    private UserTicketMapper userTicketMapper;

    @Autowired
    private RedisBloomFilter redisBloomFilter;

    @Transactional(rollbackFor = Exception.class)
    public void wrong() {
        AddCondition addCondition = AddCondition.create().keyPrefix("news").keyName("user2").exceptionInsert(500L).fpp(0.001);
        redisBloomFilter.add(addCondition,"推送1");
        userTicketMapper.insert(new UserTicket().setCreateTime(LocalDateTime.now()).setTicketId(1L).setUserId(2L));
        int i = 1 / 0;

    }

    @Transactional(rollbackFor = Exception.class)
    public void right() {
        AddCondition addCondition = AddCondition.create().keyPrefix("news").keyName("user1").exceptionInsert(500L).fpp(0.001);
        redisBloomFilter.add(addCondition,"推送3");
        userTicketMapper.insert(new UserTicket().setCreateTime(LocalDateTime.now()).setTicketId(1L).setUserId(2L));

    }
}

访问两个接口查看redis、mysql的结果

 

确实只有一个成功的,即user1有值(EnableBloomFilter的事务默认不开启)

  • 限流功能

目前支持三种限流模式——滑动窗口限流、漏斗限流、令牌桶限流,这三种模式配置时,要添加fallback方法,否则会抛异常

并在后来加多一个限流组的功能来支持动态配置,但底层核心还是上面三种模式

使用方式

在接口上添加注解@EnableLimiter,会加载对应的类,aop会进行拦截并做相应的处理,通过@Import加载注册类,enableGroup开启限流组

  • 相关注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@LimiterType(mode = LimiterConstants.FUNNEL_LIMITER)
public @interface FunnelLimiter {

    /**
     * 漏斗容量
     *
     * @return
     */
    double capacity();

    /**
     * 每秒漏出的速率
     *
     * @return
     */
    double funnelRate() ;

    /**
     * 时间单位
     *
     * @return
     */
    TimeUnit funnelRateUnit() default TimeUnit.SECONDS;

    /**
     * 每次请求所需加的水量
     *
     * @return
     */
    double requestNeed() default 1;

    String fallback() default "";

    boolean passArgs() default false;

}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@LimiterType(mode = LimiterConstants.TOKEN_LIMITER)
public @interface TokenLimiter {

    /**
     * 令牌桶容量
     *
     * @return
     */
    double capacity();

    /**
     * 令牌生成速率
     *
     * @return
     */
    double tokenRate();

    /**
     * 速率时间单位,默认秒
     *
     * @return
     */
    TimeUnit tokenRateUnit() default TimeUnit.SECONDS;

    /**
     * 每次请求所需要的令牌数
     *
     * @return
     */
    double requestNeed() default 1;

    double initToken() default 0;


    String fallback() default "";

    boolean passArgs() default false;

}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@LimiterType(mode = LimiterConstants.WINDOW_LIMITER)
public @interface WindowLimiter {
    /**
     * 持续时间,窗口间隔
     *
     * @return
     */
    int during() default 1;

    TimeUnit duringUnit() default TimeUnit.SECONDS;

    /**
     * 通过的请求数
     *
     * @return
     */
    long passCount();

    String fallback() default "";

    boolean passArgs() default false;


}

fallback则是定义于本类的其他public的方法,可以设置是否传参,参数则是被拦截的方法的参数,可以在返回的方法使用这些参数

  • demo

@RestController
public class TestController2 {
 
    @GetMapping("ha")
    @WindowLimiter(during = 10,passCount = 5)
    public String test() {
        return "hihi1";
    }
    //每秒通过0.5个请求
    @GetMapping("ha2/{userName}")
    @FunnelLimiter(capacity = 5,funnelRate = 0.5,requestNeed = 1,fallback = "test",passArgs = true)
    public Result<String> test2(@PathVariable("userName")String userName) throws NoSuchMethodException {
        return Result.success("ok");
    }
    //默认为秒,该配置为每秒生成0.5个令牌
    @GetMapping("ha3")
    @TokenLimiter(capacity = 5,tokenRate = 0.5,requestNeed = 1)
    public String test3() {
        return "hihi3";
    }
    //一分钟生产一个令牌
    @GetMapping("ha4")
    @TokenLimiter(capacity = 5,tokenRate = 1,tokenRateUnit = TimeUnit.MINUTES,initToken = 5)
    public String test4() {
        return "hihi4";
    }


    public Result<String> test(String userName){
        return Result.success("对不起:"+userName+",挤不进去太多人了");
    }


}

这里给出Resul类

@Data
@AllArgsConstructor
public class Result<T> {
    private T data;
    private String msg;
    private Integer code;

    public static Result success(Object data){
        return new Result(data,"ok",0);
    }
}

下面到动态配置的功能介绍,需要在注解@EnableLimiter上配置 enableGroup=true,默认不开启

首先要定义一个限流器,下面这个demo几乎把所有配置都列出来了,其中id是最重要的,用来标记该限流器,做好配置后,需要添加相关的拦截器,本身有四个拦截器,url前缀拦截器,ip黑/白名单,和本身的限流器,按权重执行从大到小执行,可以调用order方法来更改他的权限大小,默认执行顺序为ip-url-限流,也可以自己实现相关的拦截器,但权重要做相关的调整

@Configuration
public class RateLimitConfig implements InitializingBean {
    @Autowired
    private LimiterGroupService limiterGroupService;

    @Override
    public void afterPropertiesSet() {
        //清除原来的配置
        limiterGroupService.clear("1");
        //新建
        LimiteGroupConfig config = LimiteGroupConfig.of().id("1")
                .remark("this.application").tokenConfig(
                        //令牌桶配置,下面表示令牌桶容量为5,初始桶为3,每1s生产3个令牌,每个请求消耗1个令牌
                        TokenRateConfig.of()
                                .capacity(5.0)
                                .initToken(3.0)
                                .requestNeed(1.0)
                                .tokenRate(3.0)
                                .tokenRateUnit(TimeUnit.SECONDS)
                                .build()
                ).
                        windowConfig(
                                //滑动窗口配置,下面表示10s内只允许5个通过
                                WindowRateConfig.of()
                                        .passCount(5L)
                                        .during(10L)
                                        .duringUnit(TimeUnit.SECONDS)
                                        .build()).currentMode(LimiterConstants.TOKEN_LIMITER)
                //漏斗配置,容纳量为10,每次请求容纳量-1,每3秒增加1个容纳量
                .funnelConfig(FunnelRateConfig.of()
                        .capacity(10.0)
                        .funnelRate(3.0)
                        .funnelRateUnit(TimeUnit.SECONDS)
                        .requestNeed(1.0)
                        .build())
                //黑白名单,网段 xxx.xxx.xxx./24,类似 192.168.0.0-192.168.2.1 以及 192* 分号分隔
                /*.blackRule("127.0.0.1")
                .enableBlackList(true)
                .enableWhiteList(true).
                whiteRule("192.168.0.*")
                */
                .blackRuleFallback("ip")
                //当前限流模式
                .currentMode(LimiterConstants.TOKEN_LIMITER)
                //开启统计,是统计复用该配置下的请求数
                .enableCount(true)
                //统计时间范围,如果没有则从第一次请求开始统计
                .countDuring(1L).countDuringUnit(TimeUnit.MINUTES)
                //url配置,;号分割
                .unableURLPrefix("/user;/qq")
                .enableURLPrefix("/test")
                //url匹配失败后的执行方法
                .urlFallBack("userBlack")
                .build();
        //保存到redis,也可以保存到本地
        limiterGroupService.save(config, true, false);
        //读取redis上的配置
//        limiterGroupService.reload("1");
        //添加对应的拦截器,不然切面中不会执行对应的逻辑,这里也可以实现自己的拦截器并添加上去
        limiterGroupService.addHandler(GroupHandlerFactory.limiteHandler())
                .addHandler(GroupHandlerFactory.ipBlackHandler())
                .addHandler(GroupHandlerFactory.urlPrefixHandler());
        ;
    }
}

内置了一个controller用于动态更改配置,目前主要是ip、url、限流模式、限流器的配置,更改模式时可以选择是否删掉其他限流器在redis上的缓存,url拦截器通过前面urlhanlder配置

@RestController
public class ActuatorController {

    @Autowired
    private LimiterGroupService limiterGroupService;

    @GetMapping("/redis-aux/getIp")
    public String getIp(HttpServletRequest request) {
        return IpCheckUtil.getIpAddr(request);
    }

    //更改ip规则
    @PostMapping("/redis-aux/changeIpRule")
    public LimiteGroupConfig changeRule(@RequestParam("groupId") String groupId,
                                        @RequestParam(value = "rule", required = false) String rule,
                                        @RequestParam(value = "enable", required = false) Boolean enable,
                                        @RequestParam(value = "white", required = false) Boolean white) {
        LimiteGroupConfig limiter = limiterGroupService.getLimiterConfig(groupId);
        if (white) {
            limiter.setWhiteRule(rule);
            limiter.setEnableWhiteList(enable);
        } else {
            limiter.setBlackRule(rule);
            limiter.setEnableBlackList(enable);
        }
        limiterGroupService.save(limiter, true, false);
        return limiter;
    }

    //更改url匹配规则
    @PostMapping("/redis-aux/changeUrlRule")
    public LimiteGroupConfig changeUrlRule(@RequestParam("groupId") String groupId,
                                           @RequestParam("enableUrl") String enableUrl,
                                           @RequestParam("unableUrl") String unableUrl
                                           ) {
        LimiteGroupConfig limiter = limiterGroupService.getLimiterConfig(groupId);
        if (enableUrl != null) {
            limiter.setEnableURLPrefix(enableUrl);
        }
        if (unableUrl != null) {
            limiter.setUnableURLPrefix(unableUrl);
        }
        limiterGroupService.save(limiter, true, false);
        return limiter;
    }


    //更改模式
    @PostMapping("/redis-aux/changeLimitMode")
    public LimiteGroupConfig changeMode(@RequestParam("groupId") String groupId, @RequestParam("mode") Integer mode
            , @RequestParam("removeOther") Boolean removeOther
    ) {
        LimiteGroupConfig limiter = limiterGroupService.getLimiterConfig(groupId);
        if (mode < 4 && mode > 0) {
            limiter.setCurrentMode(mode);
        }
        limiterGroupService.save(limiter, true, removeOther);
        return limiter;
    }

    //更改限流规则
    @PostMapping("/redis-aux/changeFunnelConfig")
    public LimiteGroupConfig changeFunnelConfig(@RequestParam("groupId") String groupId,
                                                @RequestParam(value = "requestNeed", required = false) Double requestNeed,
                                                @RequestParam("capacity") Double capacity,
                                                @RequestParam("funnelRate") Double funnelRate,
                                                @RequestParam(value = "funnelRateUnit", required = false) Integer funnelRateUnit
    ) {

        FunnelRateConfig config = FunnelRateConfig.of().capacity(capacity)
                .funnelRate(funnelRate).requestNeed(requestNeed)
                .funnelRateUnit(TimeUnitEnum.getTimeUnit(funnelRateUnit)).build();
        LimiteGroupConfig limiter = limiterGroupService.getLimiterConfig(groupId);
        limiter.setFunnelRateConfig(config);
        limiterGroupService.save(limiter, true, false);
        return limiter;
    }

    @PostMapping("/redis-aux/changeWindowConfig")
    public LimiteGroupConfig changeWindowConfig(@RequestParam("groupId") String groupId,
                                                @RequestParam("passCount") Long passCount,
                                                @RequestParam(value = "during", required = false) Long during,
                                                @RequestParam(value = "duringUnit", required = false) Integer mode
    ) {
        WindowRateConfig config = WindowRateConfig.of().passCount(passCount).during(during).duringUnit(TimeUnitEnum.getTimeUnit(mode)).build();
        LimiteGroupConfig limiter = limiterGroupService.getLimiterConfig(groupId);
        limiter.setWindowRateConfig(config);
        limiterGroupService.save(limiter, true, false);
        return limiter;
    }

    @PostMapping("/redis-aux/changeTokenConfig")
    public LimiteGroupConfig changeWindowConfig(@RequestParam("groupId") String groupId,
                                                @RequestParam("capacity") Double capacity,
                                                @RequestParam(value = "initToken", required = false) Double initToken,
                                                @RequestParam("tokenRate") Double tokenRate,
                                                @RequestParam(value = "requestNeed", required = false) Double requestNeed,
                                                @RequestParam(value = "duringUnit", required = false) Integer mode
    ) {
        TokenRateConfig config = TokenRateConfig.of().capacity(capacity).initToken(initToken).tokenRate(tokenRate)
                .requestNeed(requestNeed).tokenRateUnit(TimeUnitEnum.getTimeUnit(mode)).build();
        LimiteGroupConfig limiter = limiterGroupService.getLimiterConfig(groupId);
        limiter.setTokenRateConfig(config);
        limiterGroupService.save(limiter, true, false);
        return limiter;
    }

    @GetMapping("/redis-aux/getCount/{groupId}")
    public Map<String, String> changeCountConfig(@PathVariable("groupId") String groupId
    ) {
        return limiterGroupService.getCount(groupId);
    }

}

然后到使用方式,配置好后,可以在类或者方法上使用,如果在类中使用

@RestController
@LimiteGroup(groupId = "1", fallback = "test")
public class TestController {

    @GetMapping("/ok")
    public String ok() {
        return "ok";
    }

    @GetMapping("/user")
    public String user() {
        return "user";
    }
 @GetMapping("/user/t")
    @LimiteExclude
    public String usert() {
        return "usert";
    }

    public String userBlack() {
        return "非法前缀访问";
    }
    public String ip() {
        return "ip错误";
    }
    public String test() {
        return "too much request";
    }
}

 

可以访问ActuatorController 的接口进行相关的配置,下面的统计功能采用滑动窗口+分桶计算该段时间的qps,是对单个应用的数据统计

 

更改限流模式

此时可以看出,每个接口对应自己的限流器,但是配置是公用的,修改配置,token对应的模式为2,现在改为window模式(1)

如果removeOther=true,则会删除其他限流器在redis上的配置,底层实现是之前的限流器,需要时会重新生成。

此时查看redis

有两个限流器出来了,更改以后返回限流提示的次数更多,因为上面的滑动窗口配置只允许10s内通过5次

url前缀

如果是合法的url前缀则直接通过,默认为"/*"属于继续后面的逻辑过程

ip地址也差不多,在先前的配置项里可以找到,目前支持网段,范围和*通配符

如果在使用了@LimiteGroup注解上的类想排除某些方法,可以用@LimiteExclude取消拦截链处理

展开阅读全文

代码

的 Gitee 指数为
超过 的项目

评论 (9)

加载中
没法动态调整限流值?
2020/02/13 21:13
回复
举报
1016644172软件作者
因为动态调整可能要加多个限流组的概念并且做相关的页面啥的,暂时还没时间做
2020/02/15 12:16
回复
举报
1016644172软件作者
后台做了动态配置的,暴露了相关接口,但管理界面估计得抽空再写了
2020/02/17 22:48
回复
举报
Spring boot1.5支持吗
2020/01/20 16:23
回复
举报
1016644172软件作者
理论上是支持的,我在本地1.5版本也可以跑,如果不能跑的话,可能有依赖冲突
2020/01/21 09:45
回复
举报
年后测试下,感谢你的辛勤付出
2020/01/23 10:10
回复
举报
1016644172软件作者
哈哈,兴趣而已,疫情严重,勤洗手,出门记得戴口罩
2020/01/25 16:50
回复
举报
开发语言?
2020/01/20 08:04
回复
举报
1016644172软件作者
肯定是java。。只是之前编辑漏掉了
2020/01/21 09:14
回复
举报
更多评论
暂无内容
发表了博客
2018/08/21 11:58

ps -aux ,ps aux ,ps -ef 的区别

Linux中的ps命令是Process Status的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信息,就可以使用top命令。 要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程,而 ps 命令就是最基本同时也是非常强大的进程查看命令。使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有...

0
0
发表了博客
2019/03/26 01:05

ps aux、ps -aux、ps -ef之间的区别

Linux中的ps命令是Process Status的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信息,就可以使用top命令。 要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程,而 ps 命令就是最基本同时也是非常强大的进程查看命令。使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有...

0
0
发表于软件架构专区
2020/07/22 10:33

aux_source_directory

aux_source_directory 在目录中查找所有源文件。 aux_source_directory(<dir> <variable>) 收集指定目录中所有源文件的名称,并将列表存储在提供的变量中。 该命令旨在供使用显式模板实例化的项目使用。 模板实例化文件可以存储在Templates子目录中,并使用此命令自动收集,以避免手动列出所有实例化。 试图使用此命令来避免编写库或可执行目标的源文件列表。 尽管这似乎可行,但是CMake无法生成知道何时添加新源文件的生成系统...

0
0
发表于运维专区
2014/04/23 13:43

ps -aux|grep 详细信息

ps a 显示现行终端机下的所有程序,包括其他用户的程序。 2)ps -A 显示所有程序。 3)ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。 4)ps -e 此参数的效果和指定"A"参数相同。 5)ps e 列出程序时,显示每个程序所使用的环境变量。 6)ps f 用ASCII字符显示树状结构,表达程序间的相互关系。 7)ps -H 显示树状结构,表示程序间的相互关系。 8)ps -N 显示所有的程序,除了执行ps指令终...

0
2
发表于DevOps专区
2019/05/10 23:02

ps -aux命令详解

linux上进程有5种状态: 1. 运行(正在运行或在运行队列中等待) 2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号) 3. 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生) 4. 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放) 5. 停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行) 1)ps a 显示现行终端机下的所有程序,包括其他用户的程序。 2)ps -A 显示所有程...

0
0
2020/12/22 18:41

aux-自动化框架-email@protojour.com

aux-自动化框架-email@protojour.com 发布:2020-12-22 18:41:28.327869 作者:email@protojour.com ### 作者邮箱:UNKNOWN ### 首页:UNKNOWN ### 文档:None ### 下载链接 UNKNOWN UNKNOWN Copy from pypi.org 查询时间:2.42ms 渲染时间:2.55ms 本文同步分享在 博客“zhenruyan”(other)。 如有侵权,请联系 support@oschina.cn 删除。 本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。...

0
0
发表于大前端专区
2016/05/20 21:04

ps aux |grep nginx

查看nginx进程 ps aux |grep nginx

0
0
发表于开发技能专区
2018/01/14 02:05

ps aux与ps -ef的区别

优先使用 ps -ef Linux中的ps命令是Process Status的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信息,就可以使用top命令。 要对进程进行监测和控制,首先必须要了解当前进程的情况,也就是需要查看当前进程,而 ps 命令就是最基本同时也是非常强大的进程查看命令。使用该命令可以确定有哪些进程正在运行和运行的状态、进程...

0
9
发表了博客
2019/08/02 14:12

ps -ef 和ps -aux的区别

在 linux 显示进程的命令是ps ,常用的是 ps -ef,今天看到了还有一个ps -aux,查询了资料,这里总结一下 那么ps -ef 和ps -aux 有什么区别呢? 其实区别不是很大,这就要追溯到Unix系统中的两种风格,System V风格和BSD 风格,ps aux最初用到Unix Style中,而ps -ef被用在System V Style中,两者输出略有不同。目前大部分Linux系统都是支持使用这两种方式。 1.ps -ef 如下 列名 含义 UID 系统用户名 PID 进程的ID PPID 父进程I...

0
0
发表于运维专区
2014/09/23 11:23

ps aux 输出 参数 含义 详解

ps aux 输出 参数 含义 详解 运行 ps aux 的到如下信息: ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND smmsp 3521 0.0 0.7 6556 1616 ? Ss 20:40 0:00 sendmail: Queue runner@01:00:00 f root 3532 0.0 0.2 2428 452 ? Ss 20:40 0:00 gpm -m /dev/input/mice -t imps2 htt 3563 0.0 0.0 2956 196 ? Ss 20:41 0:00 /usr/sbin/htt -retryonerror 0 htt 3564 0.0 1.7 29460 3704 ? Sl 20:41 0:00 htt_server...

0
0
没有更多内容
加载失败,请刷新页面
点击加载更多
加载中
下一页
暂无内容
9 评论
34 收藏
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部