PostgreSQL 从源码找出哪些操作需要超级用户权限 - 阿里云rds_superuser和superuser有什么区别...

标签

PostgreSQL , 超级用户 , superuser


背景

在数据库中哪些操作需要超级用户的权限才能执行?

这个问题翻文档可能翻不全面,或者是已经比较难以完成的任务。

但是从源码里面是比较好找出这个答案的。

权限

例如

postgres=# select * from pg_authid;rolname      | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
-------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------postgres          | t        | t          | t             | t           | t           | t              | t            |           -1 |             | pg_signal_backend | f        | t          | f             | f           | f           | f              | f            |           -1 |             | test              | f        | t          | f             | f           | t           | f              | f            |           -1 |             | dba               | f        | t          | f             | f           | t           | f              | f            |           -1 |             | test1             | f        | t          | f             | f           | f           | f              | f            |           -1 |             | digoal            | f        | t          | f             | f           | t           | f              | f            |           -1 |             | a                 | f        | t          | f             | f           | t           | f              | f            |           -1 |             | b                 | f        | t          | f             | f           | t           | f              | f            |           -1 |             | 
(8 rows)

rolsuper 就表示是否具备超级用户权限。

代码中如何判断超级用户

src/backend/utils/misc/superuser.c

/** The Postgres user running this command has Postgres superuser privileges*/
bool
superuser(void)
{return superuser_arg(GetUserId());
}/** The specified role has Postgres superuser privileges*/
bool
superuser_arg(Oid roleid)
{bool            result;HeapTuple       rtup;/* Quick out for cache hit */if (OidIsValid(last_roleid) && last_roleid == roleid)return last_roleid_is_super;/* Special escape path in case you deleted all your users. */if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)return true;/* OK, look up the information in pg_authid */rtup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));if (HeapTupleIsValid(rtup)){result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;  // 最终还是读取pg_authid中的rolsuper字段  ReleaseSysCache(rtup);}else{/* Report "not superuser" for invalid roleids */result = false;}/* If first time through, set up callback for cache flushes */if (!roleid_callback_registered){CacheRegisterSyscacheCallback(AUTHOID,RoleidCallback,(Datum) 0);roleid_callback_registered = true;}/* Cache the result for next time */last_roleid = roleid;last_roleid_is_super = result;return result;
}

在PostgreSQL代码里面,通过FormData_pg_authid结构来表示pg_authid的表结构

CATALOG(pg_authid,1260) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2842) BKI_SCHEMA_MACRO
{NameData    rolname;        /* name of role */bool        rolsuper;       /* read this field via superuser() only! */bool        rolinherit;     /* inherit privileges from other roles? */bool        rolcreaterole;  /* allowed to create more roles? */bool        rolcreatedb;    /* allowed to create databases? */bool        rolcatupdate;   /* allowed to alter catalogs manually? */bool        rolcanlogin;    /* allowed to log in as session user? */bool        rolreplication; /* role used for streaming replication */int32       rolconnlimit;   /* max connections allowed (-1=no limit) *//* remaining fields may be null; use heap_getattr to read them! */text        rolpassword;    /* password, if any */timestamptz rolvaliduntil;  /* password expiration time, if any */
} FormData_pg_authid;#undef timestamptz/* ----------------*      Form_pg_authid corresponds to a pointer to a tuple with*      the format of pg_authid relation.* ----------------*/
typedef FormData_pg_authid *Form_pg_authid;

代码中如何判断用户是否有replication的权限

以此类推,

src/backend/utils/init/miscinit.c

/** Check whether specified role has explicit REPLICATION privilege*/
bool
has_rolreplication(Oid roleid)
{bool            result = false;HeapTuple       utup;utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));if (HeapTupleIsValid(utup)){result = ((Form_pg_authid) GETSTRUCT(utup))->rolreplication;ReleaseSysCache(utup);}return result;
}

人肉时间, 找出需要判断超级用户的地方

grep -r "superuser()" *contrib/file_fdw/file_fdw.c:    if (catalog == ForeignTableRelationId && !superuser())
contrib/dblink/dblink.c:        if (!superuser())
contrib/dblink/dblink.c:        if (!superuser())
contrib/pgstattuple/pgstatindex.c:      if (!superuser())
contrib/pgstattuple/pgstatindex.c:      if (!superuser())
contrib/pgstattuple/pgstatindex.c:      if (!superuser())
contrib/pgstattuple/pgstatindex.c:      if (!superuser())
contrib/pgstattuple/pgstatindex.c:      if (!superuser())
contrib/pgstattuple/pgstattuple.c:      if (!superuser())
contrib/pgstattuple/pgstattuple.c:      if (!superuser())
contrib/pgstattuple/pgstatapprox.c:     if (!superuser())
contrib/pg_stat_statements/pg_stat_statements.c:        bool            is_superuser = superuser();
contrib/sepgsql/label.c:        if (!superuser())
contrib/pageinspect/brinfuncs.c:        if (!superuser())
contrib/pageinspect/brinfuncs.c:        if (!superuser())
contrib/pageinspect/brinfuncs.c:        if (!superuser())
contrib/pageinspect/brinfuncs.c:        if (!superuser())
contrib/pageinspect/fsmfuncs.c: if (!superuser())
contrib/pageinspect/ginfuncs.c: if (!superuser())
contrib/pageinspect/ginfuncs.c: if (!superuser())
contrib/pageinspect/ginfuncs.c: if (!superuser())
contrib/pageinspect/heapfuncs.c:        if (!superuser())
contrib/pageinspect/heapfuncs.c:        if (!superuser())
contrib/pageinspect/btreefuncs.c:       if (!superuser())
contrib/pageinspect/btreefuncs.c:       if (!superuser())
contrib/pageinspect/btreefuncs.c:       if (!superuser())
contrib/pageinspect/rawpage.c:  if (!superuser())
contrib/pageinspect/rawpage.c:  if (!superuser())
contrib/adminpack/adminpack.c:  if (!superuser())
contrib/adminpack/adminpack.c:  if (!superuser())
contrib/postgres_fdw/connection.c:              if (!superuser() && !PQconnectionUsedPassword(conn))
contrib/postgres_fdw/connection.c:      if (superuser())
src/include/catalog/pg_authid.h:        bool            rolsuper;               /* read this field via superuser() only! */
src/test/modules/dummy_seclabel/dummy_seclabel.c:               if (!superuser())
src/test/regress/regress.c:     if (!superuser())
src/test/regress/regress.c:     if (!superuser())
src/backend/commands/copy.c:    if (!pipe && !superuser())
src/backend/commands/trigger.c:                 if (!superuser())
src/backend/commands/dbcommands.c:                (encoding == PG_SQL_ASCII && superuser())))
src/backend/commands/dbcommands.c:                (encoding == PG_SQL_ASCII && superuser())))
src/backend/commands/dbcommands.c:      if (superuser())
src/backend/commands/opclasscmds.c:     if (!superuser())
src/backend/commands/opclasscmds.c:     if (!superuser())
src/backend/commands/opclasscmds.c:     if (!superuser())
src/backend/commands/tablespace.c:      if (!superuser())
src/backend/commands/event_trigger.c:   if (!superuser())
src/backend/commands/foreigncmds.c:     if (!superuser())
src/backend/commands/foreigncmds.c:             if (!superuser())
src/backend/commands/foreigncmds.c:     if (!superuser())
src/backend/commands/foreigncmds.c:     if (!superuser())
src/backend/commands/tsearchcmds.c:     if (!superuser())
src/backend/commands/tsearchcmds.c:     if (!superuser())
src/backend/commands/amcmds.c:  if (!superuser())
src/backend/commands/amcmds.c:  if (!superuser())
src/backend/commands/functioncmds.c:            if (!superuser())
src/backend/commands/functioncmds.c:    if (isLeakProof && !superuser())
src/backend/commands/functioncmds.c:            if (procForm->proleakproof && !superuser())
src/backend/commands/functioncmds.c:            if (!superuser())
src/backend/commands/functioncmds.c:            if (!superuser())
src/backend/commands/tablecmds.c:                       if (!superuser())
src/backend/commands/extension.c:       if (control->superuser && !superuser())
src/backend/commands/aggregatecmds.c:           if (transTypeId == INTERNALOID && superuser())
src/backend/commands/aggregatecmds.c:                   if (mtransTypeId == INTERNALOID && superuser())
src/backend/commands/alter.c:   if (!superuser())
src/backend/commands/alter.c:   if (!superuser())
src/backend/commands/alter.c:           if (!superuser())
src/backend/commands/proclang.c:                if (!superuser())
src/backend/commands/proclang.c:                if (!superuser())
src/backend/commands/user.c:            if (!superuser())
src/backend/commands/user.c:            if (!superuser())
src/backend/commands/user.c:            if (!superuser())
src/backend/commands/user.c:            if (!superuser())
src/backend/commands/user.c:            if (!superuser())
src/backend/commands/user.c:            if (!superuser())
src/backend/commands/user.c:                    if (!superuser())
src/backend/commands/user.c:            if (!superuser())
src/backend/commands/user.c:                    !superuser())
src/backend/commands/user.c:            if (!superuser())
src/backend/commands/user.c:            if (!superuser())
src/backend/commands/user.c:    if (grantorId != GetUserId() && !superuser())
src/backend/commands/user.c:            if (!superuser())
src/backend/commands/typecmds.c:        if (!superuser())
src/backend/commands/typecmds.c:                if (!superuser())
src/backend/libpq/be-fsstubs.c: if (!superuser())
src/backend/libpq/be-fsstubs.c: if (!superuser())
src/backend/catalog/system_views.sql:-- than use explicit 'superuser()' checks in those functions, we use the GRANT
src/backend/catalog/pg_proc.c:                                                          (superuser() ? PGC_SUSET : PGC_USERSET),
src/backend/tcop/utility.c:                             load_file(stmt->filename, !superuser());
src/backend/tcop/utility.c:                     if (!superuser())
src/backend/postmaster/pgstat.c:                        if (checkUser && !superuser() && beentry->st_userid != GetUserId())
src/backend/replication/slotfuncs.c:    if (!superuser() && !has_rolreplication(GetUserId()))
src/backend/replication/walreceiver.c:  if (!superuser())
src/backend/replication/walsender.c:            if (!superuser())
src/backend/replication/logical/origin.c:       if (!superuser())
src/backend/replication/logical/logicalfuncs.c: if (!superuser() && !has_rolreplication(GetUserId()))
src/backend/utils/fmgr/fmgr.c:                                          (superuser() ? PGC_SUSET : PGC_USERSET),
src/backend/utils/misc/guc.c:           !superuser())
src/backend/utils/misc/guc.c:   if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
src/backend/utils/misc/guc.c:   if (!superuser())
src/backend/utils/misc/guc.c:                                                                    (superuser() ? PGC_SUSET : PGC_USERSET),
src/backend/utils/misc/guc.c:                                                                    (superuser() ? PGC_SUSET : PGC_USERSET),
src/backend/utils/misc/guc.c:                                                    (superuser() ? PGC_SUSET : PGC_USERSET),
src/backend/utils/misc/guc.c:                                                    (superuser() ? PGC_SUSET : PGC_USERSET),
src/backend/utils/misc/guc.c:   bool            am_superuser = superuser();
src/backend/utils/misc/guc.c:   if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
src/backend/utils/misc/guc.c:                   ((conf->flags & GUC_SUPERUSER_ONLY) && !superuser()))
src/backend/utils/misc/guc.c:   if (conf->source == PGC_S_FILE && superuser())
src/backend/utils/misc/guc.c:   if (superuser())
src/backend/utils/misc/guc.c:           if (superuser())
src/backend/utils/misc/guc.c:   else if (gconf->context == PGC_SUSET && superuser())
src/backend/utils/misc/guc.c:                                                    superuser() ? PGC_SUSET : PGC_USERSET,
src/backend/utils/misc/superuser.c: *     The superuser() function.  Determines if user has superuser privilege.
src/backend/utils/init/postinit.c:                      am_superuser = superuser();
src/backend/utils/init/postinit.c:              am_superuser = superuser();
src/backend/utils/init/postinit.c:              if (!superuser() && !has_rolreplication(GetUserId()))
src/backend/utils/adt/misc.c:   if (superuser_arg(proc->roleId) && !superuser())
src/backend/utils/adt/genfile.c:        if (!superuser())
src/backend/utils/adt/genfile.c:        if (!superuser())
src/backend/utils/adt/genfile.c:        if (!superuser())
src/backend/utils/adt/genfile.c:        if (!superuser())
src/bin/psql/prompt.c:                                  if (is_superuser())

去代码里面看吧,举一些例子

例子

1. 只有超级用户可以修改或设置file_fdw foreign table的options

contrib/file_fdw/file_fdw.cif (catalog == ForeignTableRelationId && !superuser())ereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("only superuser can change options of a file_fdw foreign table")));

2. 只有超级用户能读取数据库所在服务器的文件

src/backend/utils/adt/genfile.cDatum
pg_read_file(PG_FUNCTION_ARGS)
{
...if (!superuser())ereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),(errmsg("must be superuser to read files"))));Datum
pg_read_binary_file(PG_FUNCTION_ARGS)
{
...if (!superuser())ereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),(errmsg("must be superuser to read files"))));

3. 只有超级用户可以查看需要超级用户权限才能查看的参数

src/include/utils/guc.h/** bit values in "flags" of a GUC variable*/
#define GUC_LIST_INPUT                  0x0001  /* input can be list format */
#define GUC_LIST_QUOTE                  0x0002  /* double-quote list elements */
#define GUC_NO_SHOW_ALL                 0x0004  /* exclude from SHOW ALL */
#define GUC_NO_RESET_ALL                0x0008  /* exclude from RESET ALL */
#define GUC_REPORT                              0x0010  /* auto-report changes to client */
#define GUC_NOT_IN_SAMPLE               0x0020  /* not in postgresql.conf.sample */
#define GUC_DISALLOW_IN_FILE    0x0040  /* can't set in postgresql.conf */
#define GUC_CUSTOM_PLACEHOLDER  0x0080  /* placeholder for custom variable */
#define GUC_SUPERUSER_ONLY              0x0100  /* show only to superusers */
#define GUC_IS_NAME                             0x0200  /* limit string to NAMEDATALEN-1 */
#define GUC_NOT_WHILE_SEC_REST  0x0400  /* can't set if security restricted */
#define GUC_DISALLOW_IN_AUTO_FILE 0x0800                /* can't set insrc/backend/utils/misc/guc.cif (restrict_superuser &&(record->flags & GUC_SUPERUSER_ONLY) &&!superuser())ereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("must be superuser to examine \"%s\"", name)));
...

4. 只有超级用户能执行alter system

src/backend/utils/misc/guc.cif (!superuser())ereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),(errmsg("must be superuser to execute ALTER SYSTEM command"))));

5. 只有超级用户能创建language

src/backend/commands/proclang.c/** Check permission*/if (!superuser()){if (!pltemplate->tmpldbacreate)ereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),errmsg("must be superuser to create procedural language \"%s\"",stmt->plname)));if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,get_database_name(MyDatabaseId));}

如果你发现报错中包含了权限错误的问题,也可以使用这个方法找到对应的代码。

\set VERBOSITY verbosetest=> \set VERBOSITY verbose
test=> create role b replication;
ERROR:  42501: must be superuser to create replication users
LOCATION:  CreateRole, user.c:319对应的代码在user.c的319行, CreateRole函数中.  

就举这些例子,其他的可以自己看一下。

阿里云rds_superuser和superuser有什么区别

为了维护便利,阿里云RDS PostgreSQL开放了一个权限名为rds_superuser给用户,比superuser少一些权限,主要是文件操作相关的,并且不能越权做superuser能做的事情。

相比普通用户,rds_superuser多了以下权限。

-- 创建插件
create extension ?;  -- 创建非superuser,repliction权限用户
create role ?;  -- 非supuer owned对象的操作
alter table test.test rename to test1;
alter table test.test1 owner to test_rdssuper;
alter table test.test1 rename to test;
alter table test.test owner to test_norm;-- SET SESSION AUTHORIZATION、SET ROLE可以set非superuser用户
set role to test_norm;
reset role;-- 所有对象的vacuum、analyze操作
vacuum pg_class;
analyze pg_class;-- pg_stat_reset (pgstat_reset_counters) pg_stat_reset_shared(pgstat_reset_shared_counters)
select pg_stat_reset();
select pg_stat_reset_shared('bgwriter');-- pgstat_reset_single_counter
select pg_stat_reset_single_table_counters('test.test'::regclass::oid);
select pg_stat_reset_single_function_counters('pg_stat_get_activity'::regproc::oid);-- pg_stat_get_activity pg_stat_get_backend_activity pg_stat_get_backend_waiting pg_stat_get_backend_activity_start pg_stat_get_backend_xact_start pg_stat_get_backend_start pg_stat_get_backend_client_addr pg_stat_get_backend_client_port-- select pg_stat_get_activity()
SELECT pg_stat_get_backend_pid(s.backendid) AS pid, pg_stat_get_backend_activity(s.backendid) AS query,pg_stat_get_backend_waiting(s.backendid) AS waiting, pg_stat_get_backend_xact_start(s.backendid) AS xact_start, pg_stat_get_backend_start(s.backendid) AS bd_start, pg_stat_get_backend_client_addr(s.backendid) AS ip, pg_stat_get_backend_client_port(s.backendid) AS port FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;-- pgstatindex pgstatindexbyid pgstatginindex pg_relpages pg_relpagesbyid pgstattuple 
create extension pgstattuple; 
SELECT * FROM pgstattuple('pg_catalog.pg_proc'); 
SELECT * FROM pgstatindex('pg_cast_oid_index'); 
SELECT * FROM pgstatginindex('test_gin_index'); -- pg_stat_statments-- 中文分词相关
CREATE EXTENSION zhparser;
CREATE TEXT SEARCH CONFIGURATION testzhcfg (PARSER = zhparser);
ALTER TEXT SEARCH CONFIGURATION testzhcfg ADD MAPPING FOR n,v,a,i,e,l WITH simple;-- finish prepared transaction,提交或回滚两阶段提交的事务
\c - test_norm
begin;
insert into test.test values(2);
prepare transaction 't1';
\c - test_rdssuper
select * from pg_prepared_xacts ;
commit prepared 't1';-- alter type owner
\c - test_norm
CREATE TYPE compfoo AS (f1 int, f2 text); 
\c - test_rdssuper
alter type compfoo owner to test_rdssuper; -- 允许rds_superuser用户设置session_preload_libraries,以便于用户使用pg_hint_plan等
alter role all set session_preload_libraries = 'pg_hint_plan';
alter role all set set pg_hint_plan.debug_print = on;
\c - superuser
/*+ SeqScan(test.test) */ select * from test.test;
\c - test_rdssuper
/*+ SeqScan(test.test) */ select * from test.test;-- 支持设置session_preload_libraries,设置的值必须是rds_available_extensions里面的插件
alter role all set session_preload_libraries = 'plperlu';  -- ERROR: invalid value for parameter "session_preload_libraries": "plperlu"
alter role all set session_preload_libraries = 'plperl,postgis';-- grant role to
grant test_norm to test_rdssuper;-- revoke role from
revoke test_norm from test_rdssuper;-- rds_superuser可以set
SET SESSION AUTHORIZATION ?;-- 允许rds_superuser通过dblink连接本地数据库,不需要配置port,host,ip,只需要指定dbname-- 支持oss_fdw-- 创建RDS实例时的超级用户自带了replication角色,允许用来做流复制-- 允许rds_superuser设置temp_file_limit参数-- 允许rds_superuser修改schema
grant all on schema test to test_another;

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

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

相关文章

linux c之通过消息队列实现进程通信

1、消息队列的介绍 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一…

Asp.Net Core部署:早知道,还是docker!以及一点碎碎念

前言AspNetCore技术栈在我们团队里的使用也有一段时间了,之前的部署方式一直是本地编译之后上传可执行文件到服务器,使用supervisor来管理进程这种很原始的方式。参考之前的文章:Asp.Net Core学习笔记:(五)…

04-快速排序

数据结构和算法 基于《算法图解》—Aditya Bhargava 和《数据结构》—严蔚敏 第4章 快速排序 4.1 分而治之 divide and conquer , 简称D&C:一种著名的递归式问题解决方法。 例子1: 假设你是农场主,有一小块土地。要求将这块地均匀地分…

android studio no marked region found along edge Found along top edge

由于种种原因,导致9图已经不是9图格式了,但是在Eclipse里面不会报错,在android studio 里面会报错 Error:9-patch image D:\download\avatar-android-master\avatar-android-master\sample\src\main\res\drawable-hdpi\abc_list_divider_holo…

lisp画靶子 visual_基于VisualLISP的AutoCAD绘图命令的二次开发_沈良翼

2009AutoCAD是由美国Autodesk公司于20世纪80年代初为微机上应用CAD技术而开发的绘图程序软件包,经过不断的完善,现已经成为国际上广为流行的绘图工具。AutoCAD允许用户定制菜单和工具栏,并能利用内嵌语言Autolisp、VisualLisp、VBA、ADS、ARX…

.Net相关

Lucene 全文搜索 http://lucenenet.apache.org/ Memcached 分布式缓存 http://memcached.org/ selenium UI自动化测试 http://docs.seleniumhq.org/ TestDriven.Net Unit Test http://www.testdriven.net/default.aspx MySql 数据库 http://dev.mysql.com/ dotPeek 反编译 http…

linux c之((void *) - 1)是啥意思

1、问题 今天看到进程通信通过使用内存共享来实现,看到了((void *)-1),当时一脸蒙逼,不知道什么意思。 2、理解 我一开始以为是空指针减1,自己好傻逼 实际意思是((void *)-1)是把-1转换成指针0xFFFFFFFF 3、总结 当一个函数返…

Linux下安装compsoer ,并使用composer安装laravel

为什么80%的码农都做不了架构师?>>> 1、composer安装 https://getcomposer.org/download/打开composer官网。根据提示linux下可以使用php安装。 php -r "copy(https://getcomposer.org/installer, composer-setup.php);" php -r "if (ha…

AspNetCore在docker部署时遇到一个小坑

哦吼之前刚说了尝试了使用docker来部署AspNetCore应用(Asp.Net Core部署:早知道,还是docker!以及一点碎碎念),结果这才刚上班就遇到问题了 …我这项目用的数据库是Oracle,之前直接运行没啥问题,…

JS篇 学习笔记

ECMA Script API: Array.prototype.splice(start, deleteCount, value ...) 数组操作中有:push、pop、unshift左移入、shift左进出;splice不仅可以完成删除操作,而且还可以从中间插入:当deleteCount参数为0时就可以将后面的多个参…

05-散列表

数据结构和算法 基于《算法图解》—Aditya Bhargava 和《数据结构》—严蔚敏 第5章 散列表 假设你在一家杂货店上班。有顾客来买东西时,你得到一个本子中查找价格。如果本子的内容不是按字母顺序来排序的,你可能为查找苹果价格而浏览每一页&#xff0c…

疯狂ios讲义疯狂连载之实现游戏逻辑(2)

13.6.5 定义获取通道的工具方法这里所谓的通道指的是一个方块上、下、左、右4个方向上的空白方块图13.10显示了一个方块四周的通道。图13.10 方块四周的通道下面是获取某个坐标点四周通道的4个方法。程序清单codes/13/Link/Link/sources/board/FKGameService.m13.6.6 没有转折点…

linux之进程间通信--使用信号

一、什么是信号用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中的进程捕获到这个信号…

opencv 平面法向量_在OpenCV中绘制平面的法向量

我使用2D条形码识别3D空间中的平面,我想绘制相对于其中心的法线。这是我用来计算正常的代码def compute_normal(camera, board, bounds, frame):extrinsics, ip, op get_extrinsics(camera, frame, board, bounds)extrinsic extrinsics[0]if not extrinsic: retur…

CentOS升级Python2.7及安装pip

CentOS升级Python2.7及安装pip<?xml version"1.0" encoding"UTF-8"?> CentOS升级Python2.7及安装pip1) 升级Python2.7?1234567891011121314151617181920212223242526272829303132python -V # 查看版本&#xff1a;Python 2.6.6mkdir -p ~/Env/py…

解决Maven工程中报 Missing artifact jdk.tools:jdk.tools

2019独角兽企业重金招聘Python工程师标准>>> 解决方法&#xff1a; 在pom.xml中添加如下依赖&#xff1a; <dependency> <groupId>jdk.tools</groupId> <artifactId>jdk.tools</artifactId> <version>…

回到地球之后,这个男人创建了Ubuntu

文 | 大东出品 | OSC开源社区&#xff08;ID&#xff1a;oschina2013&#xff09;2002 年&#xff0c;莫斯科当地时间 4 月 25 日 9 时 26 分&#xff0c;满载着补给和 3 名宇航员的“联盟-TM 号”航天飞船在“联盟 U”火箭的推进下飞往国际空间站。同行的三人中&#xff0c;年…

Hadoop完全分子式环境搭建—问题及解决办法

Hadoop完全分布式环境搭建 ps:本人是按照尚硅谷的教程搭建的&#xff0c;版本hadoop2.7&#xff0c;centos版本6&#xff0c;一台主机&#xff0c;两台从机。 一&#xff0e;版本问题 1.尽量使用hadoop版本2&#xff0c;尽量不要使用最新版本3。因为会出现无法解决的问题&…

linux c之perror和exit使用总结

一、perror介绍 perror函数用一种简单统一的方式报告错误。例如,一个程序试读一个不存在的磁盘文件,操作系统除了“出错了!”,这时,库函数首先会将代表操作出错的具体原因的错误代码保存到全局整型变量errono(在errno.h中定义),然后它再将错误提示传给用户程序。perror…

autoload.php beanbun_Beanbun: 简单开放的 PHP 爬虫框架

BeanbunBeanbun 是用 PHP 编写的多进程网络爬虫框架&#xff0c;具有良好的开放性、高可扩展性。项目地址&#xff1a;github.com/kiddyuchin.…文档地址&#xff1a;beanbun.org由来我希望有这样一个爬虫框架&#xff1a;在简单需求的情况下&#xff0c;可以用最少的代码快速建…