个人使用 sudo 方法

sudo

作用:允许 系统管理员 授予某些用户或用户组以 其他用户身份 运行某些或所有命令的权限

  • su 用于变更为其他使用者的身份的命令,一般需要键入该使用者的密码
  • sudo 则是对 su 使用的简化,不需要 su 琐碎的操作步骤,更佳的便捷且对权限的操纵更细腻
  • Sudo 是免费软件,遵守 ISC 式许可证,相关详情

基本安装

虽然 sudo 在大多数 Linux 系统上会自带,但这不是绝对的事情

  • 如果是使用 Debian 系统或其分支系统使用如下命令,想了解 Debian 包管理可以查看 此处

    apt install sudo
    
  • 如果是使用 Ret Hat 相关的系统及其分支可以使用如下命令

    yum install sudo
    
  • 如果需要想有更多自定义可以进行源码手动编译安装,官方安装说明

配置 sudo

sudo 支持用于安全策略、审计和输入或输出日志记录的插件架构

  • 默认安全策略是 sudoers,sudoers 策略插件作用是 控制用户使用 sudo 时权限的范围
  • 第三方可以开发和分发他们自己的插件以与 sudo 前端无缝协作,一般并情况并不会运用到,如果想要了解可查看 此处

sudoers

sudoers 安全策略要求大多数用户在使用 sudo 之前进行 身份验证,如果满足下列条件则不需要密码

  • 调用用户是root用户
  • 目标用户与调用用户相同
  • 策略已禁用用户或命令的身份验证
  • 可能支持凭证缓存,以允许用户在 sudo 一段时间内再次运行而无需身份验证,默认情况下会以每个终端为基础缓存凭据 5 分钟

注意:与 su 不同之处在 sudoers 需要身份验证时,它会验证 调用用户的凭据 而不是 目标用户或根用户的凭据

  • 如果 sudo 是由 root 用户 运行的,并且设置了 SUDO_USER 环境变量,sudoers 策略将使用该值来确定实际用户是谁
  • 即使调用了根 shell,用户也可以使用该值通过 sudo 记录命令
  • 允许 -e 选项在通过 sudo 运行脚本或程序调用时仍然有用

sudoers 的管理方式通过以下两种方法

  • /etc/sudoers 文件,此方法适合个人使用
  • 可选地在 LDAP 中驱动,此方法适用于大型分布式环境,后面不提想要了解可以点击 此处

使用 /etc/sudoers 配置文件

对于默认安全策略 sudoers,应使用 visudo 程序更改配置文件,这将确保不会引入语法错误

  • visudo 使用 vi 打开 /etc/sudoers 文件,但是在保存退出时,visudo 会检查内部语法,避免用户输入错误信息
  • 所以使用 visudo 建议查询一下 vi 用法,它与 vim 相比使用时会有些许出入

sudoers 文件格式

  • 由两种类型的条目组成:别名(基本上是变量)和用户规范(指定谁可以运行什么)
  • sudoers 文件语法将使用 EBNF 描述

别名 Aliases

  • 分四类:User_Alias, Runas_Alias, Host_Alias, Cmnd_Alias

    Alias ::= 'User_Alias'  User_Alias_Spec (':' User_Alias_Spec)* |
              'Runas_Alias' Runas_Alias_Spec (':' Runas_Alias_Spec)* |
              'Host_Alias'  Host_Alias_Spec (':' Host_Alias_Spec)* |
              'Cmnd_Alias'  Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)* |
              'Cmd_Alias'   Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)*
    
    
    User_Alias ::= NAME
    User_Alias_Spec ::= User_Alias '=' User_List
    
    User_List ::= User |
                  User ',' User_List
    User ::= '!'* user name |
             '!'* #user-ID |
             '!'* %group |
             '!'* %#group-ID |
             '!'* +netgroup |
             '!'* %:nonunix_group |
             '!'* %:#nonunix_gid |
             '!'* User_Alias
    
    
    Runas_Alias ::= NAME
    Runas_Alias_Spec ::= Runas_Alias '=' 
    
    Runas_List ::= Runas_Member |
                   Runas_Member ',' Runas_List
    Runas_Member ::= '!'* user name |
                     '!'* #user-ID |
                     '!'* %group |
                     '!'* %#group-ID |
                     '!'* %:nonunix_group |
                     '!'* %:#nonunix_gid |
                     '!'* +netgroup |
                     '!'* Runas_Alias |
                     '!'* ALL
    
    
    Host_Alias ::= NAME
    Host_Alias_Spec ::= Host_Alias '=' Host_List
    
    Host_List ::= Host |
                  Host ',' Host_List
    Host ::= '!'* host name |
             '!'* ip_addr |
             '!'* network(/netmask)? |
             '!'* +netgroup |
             '!'* Host_Alias |
             '!'* ALL
    
    
    Cmnd_Alias ::= NAME
    Cmnd_Alias_Spec ::= Cmnd_Alias '=' Cmnd_List
    
    Cmnd_List ::= Cmnd |
                  Cmnd ',' Cmnd_List
    Cmnd ::= Digest_List? '!'* command |
             '!'* directory |
             '!'* Edit_Spec |
             '!'* Cmnd_Alias
    
    Digest_List ::= Digest_Spec |
                    Digest_Spec ',' Digest_List
    Digest_Spec ::= "sha224" ':' digest |
                    "sha256" ':' digest |
                    "sha384" ':' digest |
                    "sha512" ':' digest
    digest ::= [A-Fa-f0-9]+ |
               [A-Za-z0-9\+/=]+
    
    command ::= command name |
                command name args |
                command name regex |
                command name '""' |
                ALL
    command name ::= regex |
                     file name
    
    Edit_Spec ::= "sudoedit" file name+ |
                  "sudoedit" regex |
                  "sudoedit"
    
    
    NAME ::= [A-Z][0-9A-Z]*
    
    • User_Alias: 用户名别名
    • User_List: 一个或多个用户名或系统组名(以 % 为前缀)、以 UID 或 GID(以 #%# 为前缀)、网络组(以 + 为前缀)、非 Unix 组组成名称和 ID(分别以 %:%:# 为前缀)以及 User_Alias
    • Runas_Alias: 用户身份别名
    • Runas_List: 类似 User_List 但 ALL 是任意或任何的涵义
    • Host_Alias: 主机别名
    • Host_list: 由一个或多个主机名、IP 地址、网络号、网络组(以 + 为前缀)和其他别名组成
    • Cmnd_Alias: 命令别名
    • Cmnd_list: 一个或多个命令、目录或别名的列表
    • Digest_List: 一个或多个 Digest_Spec 条目的 逗号 分隔列表
    • sudo 1.9.0 开始,如果需要可以使用 Cmd_Alias 代替 Cmnd_Alias
  • 别名定义都是以下形式

    Alias_Type NAME = item1, item2, ...
    
    • Alias_Type: 别名类型
    • NAME: 由大写字母、数字、下划线字符组成的字符串,且必须以大写字母开头
    • 可以将多个相同类型的别名定义放在一行中以 冒号 : 分隔

用户规范

  • 用户规范确定用户可以在指定主机上运行哪些命令

    User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \
                  (':' Host_List '=' Cmnd_Spec_List)*
    
    Cmnd_Spec_List ::= Cmnd_Spec |
                       Cmnd_Spec ',' Cmnd_Spec_List
    Cmnd_Spec ::= Runas_Spec? Option_Spec* (Tag_Spec ':')* Cmnd
    
    
    Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'
    Option_Spec ::= (SELinux_Spec | Solaris_Priv_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
    
    SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')
    Solaris_Priv_Spec ::= ('PRIVS=privset' | 'LIMITPRIVS=privset')
    Date_Spec ::= ('NOTBEFORE=timestamp' | 'NOTAFTER=timestamp')
    Timeout_Spec ::= 'TIMEOUT=timeout'
    Chdir_Spec ::= 'CWD=directory'
    Chroot_Spec ::= 'CHROOT=directory'
    
    
    Tag_Spec ::= ('EXEC' | 'NOEXEC' | 'FOLLOW' | 'NOFOLLOW' |
                 'LOG_INPUT' | 'NOLOG_INPUT' | 'LOG_OUTPUT' |
                 'NOLOG_OUTPUT' | 'MAIL' | 'NOMAIL' | 'INTERCEPT' |
                 'NOINTERCEPT' | 'PASSWD' | 'NOPASSWD' | 'SETENV' |
                 'NOSETENV')
    
    • 用户规范的基本结构可以理解为 who where = (as_whom) what 描述为 who 在 where 使用 as_whom 的身份执行 what 这件事
    • who: 指使用者,比如用户或用户组等
    • where: 使用场景,比如主机或网络组等
    • as_whom: 使用身份,比如用户或用户组等
    • what: 做什么,比如命令等
  • 示例

    # 允许用户 dgb 在主机 boulder 上可以 operator 的身份执行 /bin/ls、/bin/kill、/usr/bin/lprm 中任意命令
    dgb     boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm
    
    # 允许用户 dgb 在主机 boulder 上可以用 operator 用户或 operator 组的身份执行 /bin/ls,
    # 可以用 root 身份执行 /bin/kill、/usr/bin/lprm 中任意命令
    dgb	boulder = (operator : operator) /bin/ls, (root) /bin/kill,\
    /usr/bin/lprm
    
    # 用户 alan 可以作为用户 root 或 bin 运行任何命令,可选择将组设置为 operator 或 system
    alan ALL = (root, bin : operator, system) ALL
    

    使用

    $ sudo -u operator /bin/ls
    $ sudo -u operator -g operator /bin/ls
    $ sudo -g operator /bin/ls
    

标签 Tag_Spec

  • 一个命令可能有零个或多个与之关联的标签,后续就会继承该标签,除非它被相反的标签覆盖

  • EXEC 和 NOEXEC

    如果sudo编译时带有 noexec 支持并且底层操作系统支持它,则该 NOEXEC 标记可用于防止动态链接的可执行文件本身运行更多命令

    # 用户 aaron 可以运行 /usr/bin/more, /usr/bin/vi,但将禁用 shell 转义。
    aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
    
  • FOLLOW 和 NOFOLLOW

    从版本 1.8.15 开始,除非启用 sudoedit_follow 标志,sudoedit 否则将不会打开作为符号链接的文件,如果进行覆盖则可以打开,这对标签仅对 sudoedit 命令有效,对所有其他命令都将被忽略

  • LOG_INPUT 和 NOLOG_INPUT

    在每个命令的基础上覆盖 log_input 标志的值

  • LOG_OUTPUT 和 NOLOG_OUTPUT

    在每个命令的基础上覆盖 log_output 标志的值

  • MAIL 和 NOMAIL

    这些标记通过在每个命令的基础上覆盖 mail_all_cmnds 标志的值,提供对当用户运行命令时是否发送邮件的细粒度控制

  • PASSWD 和 NOPASSWD

    默认情况下,sudo 要求用户在运行命令之前进行身份验证,但可以通过 NOPASSWD 标签修改此行为,相反 PASSWD 标签可以用来颠倒事物

    # 将允许用户 ray 在机器 rushmore 上以 root 身份运行没有密码的情况下运行 /bin/kill,对 /bin/ls, /usr/bin/lprm 则需要密码
    ray rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
    

    但是请注意,该标记对 exempt_group 设置 PASSWD 指定的组中的用户没有影响

  • SETENV 和 NOSETENV

    这些标记在每个命令的基础上覆盖 setenv 标志的值

    • 如果 SETENV 已为命令设置,则用户可以通过选项从命令行禁用env_reset标志
    • -E 选项,在命令行上设置的环境变量不受 env_check, env_delete, env_keep 施加的限制,因此只应允许受信任的用户以这种方式设置变量
    • 如果匹配的命令是 ALL,则 SETENV 该命令隐含该标记,这个默认值可以通过使用 NOSETENV 标签来覆盖
  • INTERCEPT 和 NOINTERCEPT

    如果 sudo 已使用拦截支持进行编译并且底层操作系统支持它,则该 INTERCEPT 标记可用于使命令生成的程序针对 sudoers 进行验证并记录下来,就像 sudo 直接运行它们一样

    • 这与允许 shell 转义的命令(如 shell、编辑器、分页器)结合使用很有用
    • 由于策略检查可能会在运行命令(例如执行大量子命令的 shell 脚本)时增加延迟,因此会产生额外的开销

在 sudoers 文件中的主机名、路径名和命令行参数中允许使用 POSIX.1 标准的通配符,从版本 1.9.10 开始可以对路径名和命令行参数使用正则表达式,使用 POSIX 扩展正则表达式, 强烈建议不要对命令名称使用 取反类型 的正则表达式,可能会存在规则绕过的问题

下列为 POSIX.1 标准的通配符,如果是 POSIX 扩展正则表达式可以自行查询

  • *: 匹配任意一组零个或多个字符(包括空格)
  • ?: 匹配任何单个字符(包括空格)
  • [...]: 匹配指定范围内的任意字符
  • [!...]: 匹配不在指定范围内的任何字符
  • \: 转义特殊字符,从版本 1.9.10 开始,整个路径 可以用双引号括起来,在这种情况下不需要转义

sudoers 文件范围

使用 @include@includedir 指令从当前正在解析的 sudoers 文件中包含其他 sudoers 文件

  • 除了本地的每台机器文件之外,还可以使用包含文件来保留站点范围的 sudoers 文件

    • 站点范围的sudoers文件将是 /etc/sudoers 而每台机器的文件将是 /etc/sudoers.local

      # 在 /etc/sudoers 中包含 /etc/sudoers.local
      @include /etc/sudoers.local
      
    • @includedir 指令可用于创建一个 sudoers.d 目录,系统包管理器可以将 sudoers 文件规则放入其中作为包安装的一部分,文件按排序的词法顺序进行解析

  • 编写注意:特殊字符和保留字

    • # 在 sudoers 文件中作为 注释符
    • ! 以用作列表或别名中的 逻辑非运算符
    • \ 长行换行作为 续行符
    • ALL 一个内置别名,它总是使匹配成功,正如名称任何或所有
    • 保留字:CHROOT, PRIVS, LIMITPRIVS, ROLE, TYPE, TIMEOUT, CWD, NOTBEFORE, NOTAFTER
本文转载于网络 如有侵权请联系删除

相关文章

  • 订单系统:从0到1设计思路

    概述本文主要讲述了在传统电商企业中,订单系统应承载的角色,就订单系统所包含的主要功能模块梳理了设计思路,并对订单系统未来的发展做了一些思考。1.订单系统在企业中的角色在搭建企业订单系统之前,需要先梳理企业整体业务系统之间的关系和订单系统上下游关系,只有划分清业务系统边界,才能确定订单系统的职责与功能,进而保证各系统之间高效简洁的工作。2.订单系统与各业务系统的关系(1)对外系统:所有给企业外部用户使用的系统都在这一层,包括官网、普通用户使用的C端,还包括给商户使用的商家后台和在各个销售渠道进行分销的系统,比如与银行信用卡中心合作、微信合作在合作商的平台露出本企业的产品。这类系统站在与客户接触的最前线,是公司实现商业模式的桥头堡。(2)管理中后台:每个C端的业务形态都会有一个对应的系统模块,如负责管理平台交易的订单系统,管理优惠信息的促销系统,管理平台所有产品的产品系统,以及管理所有对外系统显示内容的内容系统等。(3)公共服务系统:随着企业的发展,信息化建设到达一定程度后,企业需要将通用功能服务化、平台化,以保证应用架构的合理性,提升服务效率。这类系统主要给其他应用系统提供基础服务能力支

  • 连接到Oracle数据库以及其安装方法

    如何连接到Oracle数据库?经过前几章的介绍,我们已经了解了什么是Oracle数据库以及其安装方法,那么本章节,将和大家说说如何使用SQL * plus和SQL Developer 工具连接到Oracle数据库服务器。使用SQL * Plus连接Oracle数据库服务器SQL * Plus是交互式查询工具,我们在安装Oracle数据库服务器或客户端时会自动安装。SQL * Plus有一个命令行界面,允许您连接到Oracle数据库服务器并交互执行语句。注意:如果有使用过MySQL或PostgreSQL,SQL * plus与MySQL中的mysql程序或PostgreSQL中的psql类似。我们可以在终端输入sqlplus命令,以此来在Linux或Window中启动SQL * Plus。sqlplus复制以Windows 10系统为例,在Windows的“开始”菜单的“程序”文件夹中找到SQL * Plus程序,如下所示:启动SQLPlus图标时,会提示输入用户名和密码。输入在安装Oracle数据库服务器期间设置的用户名和密码。如果不知道要使用哪个帐户,请询问安装数据库的管理员。假设要

  • 分布式和微服务有什么区别

    最近有朋友面试被问到这个问题,好像自己也没好好想过这个问题,所以大概整理了下。 微服务准确的说是微服务架构,而分布式则有分布式系统和分布式架构之说,为了不引起不必要的误会,这里统一指分布式架构。 先看下定义:1、微服务架构微服务最早由软件开发大师MartinFlower提出,以下是中文翻译: 微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并且可通过全自动部署机制独立部署。这些服务共用一个最小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储技术。https://blog.csdn.net/jason_wang1989/article/details/88321698微服务的九大特征:组件化与服务围绕业务功能的组织产品不是项目智能端点和哑管道分散治理/去中心化治理分散数据管理/去中心化数据管理基础设施自动化容错性设计演进性设计 2、分布式架构网上搜了一圈也没有准确的定义,我们简单点,如果是分布式系统,我们说说这个系统是分布式架构,看下分布式系统的定义:

  • Tungsten Fabric架构详解vRouter体系结构

    TungstenFabric项目是一个开源项目协议,它基于标准协议开发,并且提供网络虚拟化和网络安全所必需的所有组件。项目的组件包括:SDN控制器,虚拟路由器,分析引擎,北向API的发布,硬件集成功能,云编排软件和广泛的RESTAPI。 先来看一张TungstenFabricvRouter功能组件的概念视图。 vRouter代理在主机操作系统的用户空间中运行,而转发器可以是内核模块,在使用DPDK时在用户空间中运行,或者在可编程网络接口卡(也称为“智能NIC”)中运行。这些选项在后续文章中有更详细的描述,这里说明了更常用的内核模块模式。 代理与控制器保持会话,并发送其需要的VRF、路由和访问控制列表(ACL)的信息。代理将信息存储在自己的数据库中,并使用该信息配置转发器。接口连接到VRF,每个VRF中的转发信息库(FIB)都配置有转发条目。 每个VRF都有自己的转发表和流表,然而MPLS和VXLAN表在vRouter中是全局的。转发表包含目的地的IP和MAC地址的路由,并且IP到MAC关联用于提供代理ARP功能。当VM接口启动时,vRouter选择MPLS表中的标签值,并且这些值仅

  • 精通Excel数组公式001:我们为什么需要数组公式

    导语:对于很多人来说,数组公式是一个很神秘的事物,给人的印象是很难、不好理解,也不需要,虽然经常听说,偶尔也见到,但望而却步。然而,就我的学习过程和感受来说,只要理解了其运行原理,举一反三,经常运用,数组公式其实并不如想像中的那么难。下面是MikeGirvin认为学习数组公式的一些理由:1.你喜欢让Excel无所不能,你感兴趣的是使用公式让Excel实现不可能的事。2.你知道如何创建公式,想进一步提高Excel技术,进入创建高级公式的高一级水平。3.你已经听说过数组公式,知道在某些情形下数组公式是最有效的解决方案,但不知道如何创建它们。4.你使用数组公式并意识到它们表现出来的一些缺点(例如更长的计算时间),你想学习如何创建更有效率的数组公式。下面是MikeGirvin认为数组公式有用的一些理由:1.有时候,使用数组公式是解决问题的唯一方法,如下图1所示。 图1:如果不使用数据透视表,在Excel2010以前的版本中没有AGGREGATE函数,使用数组公式是有效的解决方案。2.数组公式可以取代中间的计算步骤,提供单个公式解决方案,如下图2所示。图2:如果想在列D中计算总成本前避免使用查找

  • 互联网企业如何有效落地SDL

    前言笔者在实施SDL方面有多年的经验,实施过微软厚重的SDL,实施过互联网企业粗糙的SDL,目前在落地标准化自动化的SDL,在此将我的经验分享出来。为了让大家更好的理解SDL实施的过程,本文尽量以口语化叙事的方式描述SDL实施的过程。当然每家公司的devops和实际的开发流程不一样,所以实施SDL不能照搬照套,还是得结合自己公司的实际情况。越来越多的安全招聘JD要求会SDL建设,比如安全负责人、安全专家、web安全等。很多企业招聘JD写了要求会建设SDL,但是他们对SDL建设的目标可能不太清楚。或许有个模糊的概念SDL是保障开发安全的,只是看到别家在招聘SDLer所以自己也要招个SDLer。甚至面试的时候压根不会问与SDL相关的任何知识,等真正开始着手建设SDL的时候就是摸着石头过河,很容易被微软厚重的SDL建设思路带偏。一、企业为什么要做SDL?我们熟知的安全防御手法大多是边界防控,例如对外通过反向代理只开放80和443端口,一般还会在反向代理后面串行一个waf做攻击拦截。边界防控实施起来比较容易而且安全收益也非常可观,所以是企业建设初期必做的事情。但是对于正常开放出去的服务如何保证

  • 【我们一起写框架】MVVM的WPF框架(四)—DataGrid

    前言这个框架写到这里,应该有很多同学发现,框架很多地方的细节,其实是违背了MVVM的设计逻辑的。没错,它的确是违背了。但为什么明知道违背设计逻辑,还要这样编写框架呢?那是因为,我们编写的是框架,是使用MVVM的概念编写框架,而并不是要完美的实现MVVM设计。两者有什么区别呢?区别就是前者是实战,后者只是个理念。在实战架构中,并不是UI的东西都一定要放在UI层写,逻辑的东西放在逻辑层写的。因为,架构的目的是让程序员更好的写代码,而不是让代码死死的固定在某一层。所以,我们在编写框架时,设计模式中该切割的东西,就不要犹豫的切割。因为,架构师是设计模式的使用者,而不是被使用者。举个例子,当你的逻辑全部提取到某一层中以后,你突然发现,该逻辑执行过程中要弹出提示框,但提示框又是属于UI层的,此时你犹豫了,把提示框移动到逻辑层,不符合设计理念,但不在逻辑层做,开发又很难受。遇到这样的情况,我们该怎么做呢?很简单,让设计理念去死吧,不要犹豫,直接把弹出提示框封装到逻辑层中即可。现实中,设计逻辑永远是要向开发逻辑低头的,因为实战永远高于理论。框架是什么?框架就是规则,规则在人类社会被称之为法律;换言之,

  • 给大家推荐8个SpringBoot精选项目

    前言2017年,曾在自己的博客中写下这样一段话:有一种力量无人能抵挡,它永不言败生来倔强。有一种理想照亮了迷茫,在那写满荣耀的地方。如今2018年已过大半,虽然没有大理想抱负,但是却有自己的小计划。下面是这一年来,自己利用闲暇周末时间搞得几个开源项目,可能群里的小伙伴很多都接触过,但是这里还是要分享给大家,与君共勉,一起学习。项目案例项目一:支付服务简介:支付服务:支付宝、微信、银联详细代码案例,目前已经1800+Star。十分钟让你快速搭建一个支付服务,内附各种教程。项目地址:https://gitee.com/52itstyle/spring-boot-pay项目二:秒杀案例简介:从0到1构建分布式秒杀系统,脱离案例讲架构都是耍流氓,码云GVP项目。这个是自5月以来最上心的一个项目,尽管只是一个案例,但是从中也学到了不少知识。项目地址:https://gitee.com/52itstyle/spring-boot-seckill项目三:邮件服务简介:邮件发送服务,文本,附件,模板,队列,多线程,定时任务实现多种功能。项目地址:https://gitee.com/52itstyle/

  • 玩转全新的 Android 8.0 Oreo 后台策略

    我们永远都需要流畅的用户体验,但很遗憾我们手上的硬件资源却总是和这个需求唱反调。这也是Android平台不断努力的切入点——从API26开始,Android对后台服务引入了严格的限制。基本上,除非您的应用在前台运行,否则系统将在几分钟内停止应用的所有后台服务。 由于对后台服务的这些限制,JobScheduler已经成为执行后台任务的实际解决方案。对于熟悉服务的开发者来说,JobScheduler使用起来通常很简单,当然也存在少量例外。我们这次就来探讨其中一个例外。假如您正在搭建一个AndroidTV应用。频道对电视应用非常重要,因此您的应用需要能够执行至少五种与频道有关的后台操作:发布频道,向频道添加节目,将有关频道的日志发送到远程服务器,更新频道的元数据,以及删除频道。在Android8.0(Oreo)之前,这五个操作中的每一个都可以在后台服务中实现。然而,从API26开始,您必须明智地决定,哪些应该沿用原有的普通后台Service,哪些应该使用JobService。如果只考虑电视App的使用场景,上述五个操作里,其实只有“频道发布”可以做成一个原有的普通后台服务。在某些场合下,频道

  • Python连接Hive操作数据库

    前言客户端连接Hive需要使用HiveServer2。HiveServer2是HiveServer的重写版本,HiveServer不支持多个客户端的并发请求。当前HiveServer2是基于ThriftRPC实现的。它被设计用于为像JDBC、ODBC这样的开发API客户端提供更好的支持。Hive0.11版本引入的HiveServer2。Python客户端连接HiveServer2python中用于连接HiveServer2的客户端有3个:pyhs2,pyhive,impyla。官网的示例采用的是pyhs2,但pyhs2的官网已声明不再提供支持,建议使用impyla和pyhive。数据库乱码问题在Python代码 conn=MySQLdb.Connect(host='localhost',user='root',passwd='root',db='python')中加一个属性: 改为: conn=MySQLdb.Connect(host='localhost',user='roo

  • 《Android》Lesson21-广播+SharedPreferences

    Week12 2016/11/29上午1-4节 一、复习上节课内容二、实现强制下线功能1、TableLayout+LoginActivity(1)设置行间距android:lineSpacingExtra设置行间距,如”3dp”。android:lineSpacingMultiplier设置行间距的倍数,如”1.2″。(2)editText.requestFocus();获取焦点androideditText获取焦点-lucky8star的专栏-博客频道-CSDN.NETAndroid中EditText中字体颜色的selector-博客频道-CSDN.NET(3)editText改变字体颜色SpannableString ss = new SpannableString("你要写的内容");//设置0-2的字符颜色ss.setSpan(new ForegroundColorSpan(Color.RED), 0, 2,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);txtInfo.setText(ss);AndroidTextView中文字通过Sp

  • 技术开发中一些名词解释

    前言现在还记得第一次面试的时候,被问HTML全称是什么,这才意识到记住全称并不是无理取闹,而是个人对这项技术的理解程度还没到。当你去了解一个技术的时候,名词是首先要掌握的,除非你只是皮毛。常规英文全称descHTTPHyperTextTransferProtocol超文本传输协议HTMLHyperTextMark-upLanguage超文本标记语言APIApplicationProgrammingInterface接口SQLStructuredQueryLanguage结构化查询语言NoSQLNotonlySQL不仅仅是sqlGUIGraphicalUserInterface图形用户界面IDEIntegratedDevelopmentEnvironment集成开发环境URLUniformResoureLocator统一资源定位符Java英文全称descJDKJavaDevelopmentKitJava开发工具JVMJavavirtualmachineJava虚拟机GCGarbagecollection垃圾回收OOObject-oriented面向对象OOPObject-oriented

  • 转:内存对齐

    内存对齐 内存对齐”应该是编译器的“管辖范围”。编译器为程序中的每个“数据单元”安排在适当的位置上。但是C语言的一个特点就是太灵活,太强大,它允许你干预“内存对齐”。如果你想了解更加底层的秘密,“内存对齐”对你就不应该再透明了。 内存对齐”应该是编译器的“管辖范围”。编译器为程序中的每个“数据单元”安排在适当的位置上。但是C语言的一个特点就是太灵活,太强大,它允许你干预“内存对齐”。如果你想了解更加底层的秘密,“内存对齐”对你就不应该再透明了。   中文名内存对齐释    义是编译器的“管辖范围”。作    用每个数据单元安排在适当的位置特    征透明 目录 1词条简介 2详细解释 ▪对齐原因 ▪对齐规则 ▪验证试验 ▪基本结论 词条简介 对于大部分程序员来说,“内存对齐”对他们来说都应该是“透明的”。 详细解释 大部分的参考资料都是如是说的: 1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件

  • Django基础十一之认证系统

    一auth模块      我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。   Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统--auth,它默认使用auth_user表来存储用户数据,使用auth模块来进行用户认证,那么需要使用人家django自带的auth_user表来存储用户的信息数据。   模块导入: fromdjango.contribimportauth 复制   那么有人就有疑问了,这个auth_user表并不是我们自己在models.py文件中创建的啊,这通过代码怎么操作啊?   其中一个往auth_user表里面添加数据的命令,可以先多添加几个用户,方便后面操作: pythonmanage.pycreatesuperuser#要通过这个指令来创建用户,因为这个指令会将你的密码加密。 复制          然后表中就有数据了:这个表里面的数据现在先关注username和password字段就可以了,其他的字段

  • 如何将jar包推送给maven管理

    命令: mvninstall:install-file-DgroupId=**-DartifactId=**-Dversion=**-Dfile=***-Dpackaging=jar-DgeneratePom=true 复制   

  • A4

    队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 很胖,刚学,照猫画虎做了登录与注册界面。 展示GitHub当日代码/文档签入记录: 暂无 接下来的计划 继续优化注册界面与登录界面 制作主界面 还剩下哪些任务 进一步完善已有界面 进一步学习前端制作 燃尽图: 有哪些困难: 前端制作的进一步学习 有哪些收获和疑问 学会了一定的安卓开发经验 与队友共同研究了前端 组员2:林志华 过去两天完成了哪些任务 描述: 前端知识学习 算法设计 按钮监听事件的学习 展示GitHub当日代码/文档签入记录: 接下来的计划 深入学习前端知识 人机交互部分完成 还剩下哪些任务 和后端的对接 获取前端信息 燃尽图: 团队共享 有哪些困难: 时间滚轮优化及如何将滚轮信息传到后端 不知如何和后端对接 有哪些收获和疑问 学习了按钮空间和滚动项控件的使用 与队友共同研究了前端如何编写 组员3:李麒 过去两天完成了哪些任务 描述: 正在搭建后台。 展示GitHub当日代码/文档签入记录:

  • 【php】Cannot validate since no PHP executable is set.的解决方法

    CannotvalidatesincenoPHPexecutableisset.Usethesetting'php.validate.executablePath'toconfigurethePHPexecutable.无法使用PHP可执行的设置。设置php.validate。executablePath配置PHP可执行文件。 这段时间看网上说visualstudiocode(VSC)这款编辑器不错,今天下载下来想试试怎么样。 默认的黑色风格是现在的主流呀,总体看着还不错,而且我下载的时候没有选择直接就是中文版的,微软对中文的支持还是不错的。 CannotvalidatesincenoPHPexecutableisset 而且可以直接添加扩展,扩展还有“图标”显示,很贴心,很方便: Usethesetting'php.validate.executablePath'toconfigurethePHPexecutable 我首先创建了一个PHP文件,出来一个“信息”提示:无法使用PHP可执行的设置。设置php.validate。executablePath配置PHP可执

  • 前端项目之react-todolist

    一、搭建好react的环境 npminstall-gcreate-react-app create-react-app.     //这一命令会在文件夹中生成package.json/node-modules/public/src/.gitignore/package-lock.json/README.md这一系列的文件 yarnstart //不会生成build,只有yarnrun build才会有压缩好的一堆文件生成 表示搭建成功。 在这里我要讲一个巨坑的经历,在上传到github的远程仓库时,出现了一直报错的情况,css/js找不到,历时超久,发现是package.json里面的homepage写错了地方,啊啊啊啊啊啊啊啊啊啊。 二、搭建基本框架 先构思一下,首先有一个h1标签,显示这是谁的待办,然后有一个文本输入框,再下面是个列表,用来存放用户所有的待办事项。 三、将输入框和待办事项列表拆分成两个不同的组件,提高代码的可维护性、可扩展性和可测试性。     四、基本框架做好之后我们来添加简单的样式,首先引入一个重置的CSS

  • 标记永久化线段树 区间更新求和

    #include<iostream> #include<cstdio> #include<cstring> usingnamespacestd; typedeflonglongll; constintMAXN=100009; intn,q; llsum[MAXN*4],add[MAXN*4]; voidbuild(intl,intr,intrt) { add[rt]=0; if(l==r){ scanf("%lld",&sum[rt]); return; } intmid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); sum[rt]=(sum[rt<<1]+sum[rt<<1|1]); } voidupdate(intl,intr,intrt,intql,intqr,intc) { sum[rt]+=c*(qr-ql+1); if(l==ql&&r==qr){ add[rt]+=c; return; } i

  • 人生哲理-4

    不一心二用,否则,工作的速度和精度都会下降 集中精力于不同工作的切换时间上 2min能搞定的事情尽快搞定 无论何时何地都要做好你自己 一时大意,一生残疾 todo让我专注地生活在当下的每一秒,又在改变着人生  

  • 数据结构与算法面试总结

    TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素? TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。

相关推荐

推荐阅读