Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions
ℹ️ 此存储库包含有关各种技术主题的问题和练习,有时与 DevOps 和 SRE 相关
📊 当前有 2624 个问题
⚠️ 您可以使用这些来准备面试,但大多数问题和练习并不代表实际的面试。请阅读常见问题了解更多详情
📄 不同的面试官专注于不同的事情。 有些人将重点放在你的简历上,而另一些人可能将重点放在方案问题或特定的技术问题上。 在这个仓库,我尽力覆盖各种类型的 DevOps 问题,供你练习和测试你的知识
📝 你可以通过提交拉取请求来添加更多练习:) 在此处阅读贡献指南
以太网简单地指的是当今最常见的局域网(LAN)类型。与跨越较大地理区域的广域网(WAN)相对,LAN是一个连接在小范围内的计算机网络,比如你的办公室、大学校园或者家庭。
MAC地址是用于识别网络上各个设备的唯一标识号码或代码。
通过以太网发送的数据包始终来自一个 MAC 地址并发送到一个 MAC 地址。如果网络适配器接收到一个数据包,它会将该数据包的目标 MAC 地址与适配器自身的 MAC 地址进行比较。
当设备向广播 MAC 地址(FF:FF:FF:FF:FF:FF)发送数据包时,它会传递给本地网络上的所有站点。以太网广播用于在数据链路层通过 ARP 解析 IP 地址到 MAC 地址。
互联网协议地址(IP 地址)是分配给连接到使用互联网协议进行通信的计算机网络上的每个设备的数字标签。IP地址具有两个主要功能:主机或网络接口识别和位置寻址。
子网掩码是一个32位的数字,用于屏蔽 IP 地址并将 IP 地址分为网络地址和主机地址。子网掩码通过将网络位设置为全部"1",将主机位设置为全部"0"来生成。在给定的网络中,总可用主机地址中始终保留两个用于特定目的,并且不能分配给任何主机。这些是第一个地址,被保留作为网络地址(也称为网络 ID),以及最后一个用于网络广播的地址。
您可以在 penguintutor.com 阅读有关OSI模型的更多信息。
单播:一对一的通信,其中有一个发送者和一个接收者。
广播:向网络中的所有人发送消息。地址 ff:ff:ff:ff:ff:ff 用于广播。
使用广播的两个常见协议是 ARP 和 DHCP。
多播:向一组订阅者发送消息。它可以是一对多或多对多的。
CSMA/CD 代表载波侦听多路访问冲突检测。
其主要目标是管理对共享介质/总线的访问,每次只有一个主机可以传输。
CSMA/CD 算法:
路由器、交换机和集线器都是用于连接局域网(LAN)中的设备的网络设备。然而,每个设备的操作方式不同,并且具有其特定的使用情况。以下是对每个设备及其之间区别的简要描述:
三个冲突域和一个广播域
路由器是一种物理或虚拟设备,用于在两个或多个分组交换的计算机网络之间传递信息。路由器检查给定数据包的目标互联网协议地址(IP地址),计算它到达目的地的最佳路径,然后相应地转发它。
网络地址转换(NAT)是一个过程,其中一个或多个本地IP地址被翻译成一个或多个全局IP地址,反之亦然,以便为本地主机提供互联网访问。
代理服务器充当您和互联网之间的网关。它是一个中介服务器,将最终用户与他们浏览的网站分离开来。
如果您使用代理服务器,互联网流量将通过代理服务器传输到您请求的地址。然后,该请求再次通过相同的代理服务器返回(有一些例外情况),然后代理服务器将从网站接收到的数据转发给您。
代理服务器根据您的使用情况、需求或公司政策提供不同级别的功能、安全性和隐私保护。
TCP 三次握手,又称为三向握手,在 TCP/IP 网络中用于建立服务器和客户端之间的连接的过程。
三次握手主要用于创建 TCP 套接字连接。它在以下情况下起作用:
TCP 在客户端和服务器之间建立连接,以保证数据包的顺序,而 UDP 不在客户端和服务器之间建立连接,也不处理数据包顺序。这使得 UDP 比 TCP 更轻便,是流媒体等服务的理想选择。
Penguintutor.com 提供了很好的解释。
默认网关是一个接入点或 IP 路由器,联网计算机利用它将信息发送到另一个网络或互联网上的计算机。
ARP 是地址解析协议(Address Resolution Protocol)的缩写。当您尝试 ping 本地网络上的一个 IP 地址(如 192.168.1.1)时,您的系统必须将 IP 地址 192.168.1.1 转换为 MAC 地址。这就需要使用 ARP 来解析该地址,ARP 也因此而得名。
系统会保存一个 ARP 查找表,其中存储了哪些 IP 地址与哪些 MAC 地址相关联的信息。当试图向某个 IP 地址发送数据包时,系统会首先查询该表,看是否已经知道该 MAC 地址。如果有缓存值,则不使用 ARP。
它代表动态主机配置协议,为主机分配 IP 地址、子网掩码和网关。它是这样工作的:
更多信息 此处
可以在同一网络上安装两个 DHCP 服务器,但不建议这样做,而且必须仔细配置,以防止冲突和配置问题。
下面介绍 SSL 隧道的工作原理:
我们应该考虑使用 IPv6 而不是 IPv4 有几个原因:
MTU 是最大传输单元(Maximum Transmission Unit)的缩写。它是指单个事务中可发送的最大 PDU(协议数据单元)的大小。
在 IPv4 协议中,路由器可以对 PDU 进行分片,然后通过事务发送所有已分片的 PDU。
使用 IPv6 协议时,它会向用户计算机发出错误信息。
错。Ping 实际上使用的是 ICMP(互联网控制报文协议),这是一种用于发送与网络通信有关的诊断信息和控制信息的网络协议。
ICMP消息被用于各种目的,包括:
NAT 是网络地址转换的缩写。它是一种在传输信息前将多个本地专用地址映射到一个公共地址的方法。希望多个设备使用一个 IP 地址的组织和大多数家用路由器一样,都会使用 NAT。
例如,你电脑的私有 IP 可能是 192.168.1.100,但你的路由器会将流量映射到它的公共 IP(如 1.1.1.1)。互联网上的任何设备都会看到来自公共 IP(1.1.1.1)而不是私人 IP(192.168.1.100)的流量。
有几个因素会影响网络性能,包括:
APIPA 是分配给设备的一组 IP 地址
当主 DHCP 服务器无法访问时分配给设备的 IP 地址
APIPA 使用的 IP 范围是169.254.0.1 - 169.254.255.254.
控制平面是网络的一部分,它决定如何将数据包路由和转发到不同的位置。
数据平面是网络中实际转发数据/数据包的部分。
它指的是监测和管理功能。
控制平面。
OSPF(开放式最短路径优先)是一种路由协议,可在各种类型的路由器上实施。一般来说,大多数现代路由器都支持 OSPF,包括思科、瞻博网络和华为等供应商的路由器。该协议设计用于基于 IP 的网络,包括 IPv4 和 IPv6。此外,它采用分层网络设计,将路由器分组为区域,每个区域都有自己的拓扑图和路由表。这种设计有助于减少路由器之间需要交换的路由信息量,提高网络的可扩展性。
OSPF 4 路由器类型有
了解有关 OSPF 路由器类型的更多信息: https://www.educba.com/ospf-router-types
延迟是指信息从信息源到达目的地所需的时间。
带宽是通信信道的容量,用于衡量后者在特定时间段内可处理的数据量。带宽越大,意味着处理的流量越多,数据传输量也就越大。
吞吐量是指在一定时间内通过任何传输通道传输的实际数据量。
延迟。要获得良好的延迟,搜索查询应转发到最近的数据中心。
吞吐量。为获得良好的吞吐量,上传数据流应被路由到未充分利用的链路。
当网络上需要传输的数据过多,而网络容量不足以满足需求时,就会出现网络拥塞。
这会导致延迟和数据包丢失增加。原因可能是多方面的,如网络使用率高、文件传输量大、恶意软件、硬件问题或网络设计问题。
为防止网络拥塞,必须监控网络使用情况,并实施策略来限制或管理需求。
00110011110100011101
互联网是一个由网络组成的网络,在全球范围内传输大量数据。
万维网是一个运行在数百万服务器上的应用程序,它位于互联网之上,可通过所谓的网络浏览器访问
ISP(互联网服务提供商)是当地的互联网公司。
开发人员经常将代码集成到共享仓库中的一种开发实践。 它的范围可以从每天或每周进行几次更改,到大规模在一个小时内进行几次更改。
验证每段代码(更改/补丁),以使更改可以安全地合并。 如今,使用自动构建来确保代码可以集成的测试更改是一种常见的做法。 它可以是一个运行在不同级别(单元,功能等)的多个测试的构建,也可以是所有或某些必须通过以将更改合并到存储库中的多个单独的构建。
你可以使用以下一项或全部:
* 成熟与尖端
* 社区规模
* 体系结构方面-代理与无代理,主控与无主控等
在可变的基础架构原则中,更改将应用到现有基础架构之上并随着时间的推移而变化
基础架构建立了变化的历史。 Ansible,Puppet和Chef这些工具
遵循可变的基础架构原则。
在不变的基础架构原则中,每项更改实际上都是新的基础架构。 所以改变
到服务器将导致新服务器而不是更新服务器。 Terraform是
遵循不变的基础架构原则的一个例子。
当配置和软件完全相同的服务器环境中的某个服务器上发生配置漂移
或服务器正在应用其他服务器无法获得的更新或配置,并且随着时间的推移,这些服务器将变为
略有不同。
这种情形可能会导致难以识别和重现的错误。
注意:交叉依赖是指你对单独的项目进行了两个或多个更改,并且你希望在相互构建中对其进行测试,而不是分别测试每个更改。
IAAS
PAAS
SAAS
边缘位置基本上是内容传递网络,它缓存数据并确保较低的延迟和更快地传递给任何位置的用户。 他们位于世界主要城市。
停止实例,使其实例类型与所需的RAM匹配,然后启动实例。
应用层:用户端(HTTP在这一层)
表示层:在应用程序层实体之间建立上下文(加密在这一层)
会话层:建立,管理和终止连接
传输层:将可变长度的数据序列从源传输到目标主机(TCP和UDP在这一层)
网络层:将数据报从一个网络传输到另一个网络(IP 层在这里)
数据链接层:提供两个直接连接的节点之间的链接(MAC在这一层)
物理层:数据连接的电气和物理规格(比特在这一一层)
广播:向网络中的所有人发送消息。 地址ff:ff:ff:ff:ff:ff:ff用于广播。
使用广播的两个常见协议是ARP和DHCP。
组播:向一组订户发送消息。 它可以是一对多或多对多。
CSMA / CD代表载波侦听多路访问/冲突检测。
它的主要重点是管理对共享媒体/总线的访问,在该共享媒体/总线上,在给定的时间点只能传输一个主机。
CSMA / CD算法:
00110011110100011101
rm
完成同样的结果吗?)df
你会得到 "找不到命令". 可能出现什么问题以及如何修复它?你能使用命令 cron
和 at
.
对于cron,使用以下格式安排任务:
任务存储在cron文件中。
通常,你将安排批处理作业。
使用 chmod
命令.
777 - 所有人有读和写和可执行权限(意味着你很懒)
644 - 拥有者有读和写的权限、其他人只有读权限
750 - 拥有者有所有权限, 组成员可以读和执行权限、其他人没有权限
dstat -t
非常适合辨别网络和磁盘问题。
netstat -tnlaup
可用于查看哪些进程在哪些端口上运行。
lsof -i -P
可以用于与netstat相同的目的。
ngrep -d any metafilter
用于将正则表达式与数据包的载荷相匹配。
tcpdump
用于捕获数据包
wireshark
与tcpdump相同的概念,但带有GUI(可选)。
dstat -t
非常适合辨别网络和磁盘问题。
opensnoop
可以用来查看正在系统上打开哪些文件(实时)。
strace
非常适合了解你的程序的功能。 它打印你的程序执行的每个系统调用。
top
显示每个进程消耗多少CPU占比
perf
是采样分析器的理想选择,通常来说,找出哪些CPU周期被“浪费”了
flamegraphs
非常适合CPU消耗可视化(http://www.brendangregg.com/flamegraphs.html)
top
检查是否有任何资源消耗你的CPU或RAM。dstat -t
来检查它是否与磁盘或网络有关。iostat
检查 I/O 统计信息grep ‘[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}’ some_file
grep -E “error|failure” some_file
grep ‘[0-9]$’ some_file
退出码(或返回码)表示子进程返回其父进程的码。
0是退出码,表示成功,而大于1的码表示错误。
每个数字都有不同的含义,具体取决于应用程序的开发方式。
我认为这是一篇可以了解更多的好博客:https://shapeshed.com/unix-exit-codes
硬链接是使用相同inode的相同文件。
软链接是使用不同inode的另一个文件的快捷方式。
可以在不同的文件系统之间创建软链接,而硬链接只能在同一文件系统内创建。
你可以通过在命令末尾指定&来实现。至于为什么,因为一些命令/过程会占用大量的时间来完成执行或永远运行
默认信号为SIGTERM(15)。 该信号可以优雅地终止进程,这意味着它可以保存当前状态配置。
SIGTERM - 终止进程的默认信号
SIGHUP - 常用用法是重新加载配置
SIGKILL - 不能捕获或忽略的信号
运行 kill -l
查看所有可用的信号
Running(运行态)
Waiting (等待态))
Stopped(暂停态)
Terminated(终止态)
Zombie(假死态)
strace
做什么的?ind /some_dir -iname *.yml -print0 | xargs -0 -r sed -i “s/1/2/g”
你可以使用命令top
和 free
你可以使用 split
命令就像这样split -l 25 some_file
在 Linux (和 Unix) 前三个描述符是:
这有一篇好的文章关于这个主题的: https://www.computerhope.com/jargon/f/file-descriptor.htm
Linux中的每个文件(和目录)都有一个索引节点,即与文件相关的存储元数据信息的数据结构
,例如文件的大小,所有者,权限等。
/etc/resolv.conf
用来做什么的? 它包含那些内容?A记录将域名指向IP地址,而PTR记录则相反,并将IP地址解析为域名。
ls
发生了什么? 提供一个详细的答案open("/my/file") = 5
read(5, "file content")
系统调用正在读 /my/file
文件 以及 5 是文件描述符数字.
ip a
你看到一个设备叫做 'lo'. 它是什么以及为什么我们需要它?traceroute
命令做什么的? 它是怎么工作的?这有一些方式去做:
任务 – 调用特定的Ansible模块
模块 – Ansible在你自己的主机或远程主机上执行的实际代码单元。 模块按类别(数据库,文件,网络等)编制索引,也称为任务插件。
Play – 在给定主机上执行的一个或多个任务
Playbook – 一个或多个Play。 每个Play可以在相同或不同的主机上执行
角色 – Ansible角色使你可以基于某些功能/服务对资源进行分组,以便可以轻松地重用它们。 在角色中,你具有变量,默认值,文件,模板,处理程序,任务和元数据的目录。 然后,你只需在剧本中指定角色即可使用该角色。
清单文件定义了在其上执行Ansible任务的主机和/或主机组。
一个清单文件的例子
192.168.1.2
192.168.1.3
192.168.1.4
[web_servers]
190.40.2.20
190.40.2.21
190.40.2.22
动态清单文件可跟踪来自一个或多个来源(例如云提供商和CMDB系统)的主机。
应该使用当使用外部源时,尤其是在环境中的主机正在自动启动和关闭,而无需跟踪这些源中的所有更改。
- name: Create a new directory
file:
path: "/tmp/new_directory"
state: directory
---
- name: Print information about my host
hosts: localhost
gather_facts: 'no'
tasks:
- name: Print hostname
debug:
msg: "It's me, {{ ansible_hostname }}"
提供完成的代码后,请始终进行彻底检查。 如果你的回答是“这将失败”,那么你是对的。 我们正在使用一个事实(ansible_hostname),
这是我们正在运行的主机上收集到的信息。 但是在这种情况下,我们禁用了事实收集(gather_facts:no),因此该变量将是未定义的,这将导致失败。
---
- hosts: all
vars:
mario_file: /tmp/mario
package_list:
- 'zlib'
- 'vim'
tasks:
- name: Check for mario file
stat:
path: "{{ mario_file }}"
register: mario_f
- name: Install zlib and vim if mario file exists
become: "yes"
package:
name: "{{ item }}"
state: present
with_items: "{{ package_list }}"
when: mario_f.stat.exists
我是 <HOSTNAME> 我的操作系统是 <OS>
替换
---
- name: Deploy /tmp/system_info file
hosts: all:!controllers
tasks:
- name: Deploy /tmp/system_info
template:
src: system_info.j2
dest: /tmp/system_info
The content of the system_info.j2 template
# {{ ansible_managed }}
I'm {{ ansible_hostname }} and my operating system is {{ ansible_distribution }}
根据可变优先级,将使用哪个?
正确的答案是 ‘toad’。
变量优先级是关于变量在不同位置设置时如何相互覆盖的。 如果你到目前为止还没有体验过,我相信你会在某个时候确定的,这使它成为一个有用的话题。
在我们的问题上下文中,顺序将是额外的var(始终覆盖任何其他变量)-> 主机事实 -> 库存变量 -> 角色默认值(最弱)。
完整的列表可以在上面的链接中找到。 另外,请注意Ansible 1.x和2.x之间存在显着差异。
def cap(self, string):
return string.capitalize()
常见的错误答案是说 Ansible 和 Puppet 是配置管理工具而 Terraform 是置备工具。 尽管从技术上讲是正确的,但这并不意味着 Ansible 和 Puppet 不能
用于配置基础结构。 另外,这根本没有解释为什么应该在 CloudFormation上 使用 Terraform。
Terraform与其他工具相比的优势:
terraform.tfstate
文件用来做什么?它跟踪创建的资源的ID,以便Terraform知道它正在管理什么。
terraform init
terraform plan
terraform validate
terraform apply
terraform init
扫描你的代码以查明你正在使用哪些提供程序并下载它们。
terraform plan
可以让你在实际执行操作之前先查看terraform即将执行的操作。
terraform apply
将提供指定的.tf文件资源。
terraform apply
改变的变量?你用这种方式: variable “my_var” {}
local-exec
and remote-exec
in the context of provisioners?这是成功创建的资源,但在配置期间失败。 Terraform将失败,并将该资源标记为“tainted”。
terraform taint
做了什么?Strimg
Integer
Map
List
terraform output
做了什么?容器和虚拟机之间的主要区别是容器使你可以虚拟化
操作系统上有多个工作负载,而对于VM,则将硬件虚拟化为
在多台计算机上运行各自的操作系统。
在以下情况下,你应该选择虚拟机:
* 你需要运行一个需要操作系统所有资源和功能的应用程序
* 你需要完全隔离和安全
在以下情况下,你应该选择容器:
* 你需要快速启动的轻量级解决方案
* 运行单个应用程序的多个版本或实例
Docker CLI 将你的请求传递给Docker守护程序。
Docker 守护程序从 Docker Hub 下载映像
Docker 守护程序使用下载的映像创建一个新容器
Docker 守护程序将输出从容器重定向到 Docker CLI,后者将其重定向到标准输出
Docker Hub是一个本地 Docker 注册表服务,可让你运行 pull 和 push 命令以从 Docker Hub 安装和部署 Docker映像。
Docker Cloud构建在Docker Hub之上,因此Docker Cloud提供了
与Docker Hub相比,你拥有更多的可选/功能。 一个例子是
群管理,这意味着你可以在Docker Cloud中创建新的群。
1. 这是一种由 Guido Van Rosum 于1991年创建的高级通用编程语言。
2. 语言被解释为CPython(用C语言编写)最常用/维护的实现。
3. 它是强类型的。 类型系统是鸭子类型和渐进式的。
4. Python注重可读性,并使用空格/缩进代替括号{}
5. python 包管理器称为PIP“ pip install packages”,具有超过200.000可用的软件包。
6. Python 附带安装了pip和一个大的标准库,为程序员提供了许多预置的解决方案。
7. 在python中,“一切”都是一个对象。
还有许多其他特性,但这是每个python程序员都应该知道的主要特性。
可变数据类型是:
List
Dictionary
Set
不可变数据类型是:
Numbers (int, float, ...)
String
Bool
Tuple
Frozenset
通常,你可以使用函数hash()来检查对象的可变性,如果它是可哈希的,则是不可变的,尽管由于用户定义的对象可能是可变的且可哈希的,所以它并不总是按预期工作
PEP8是Python的编码约定和样式指南的列表
5 种样式指南:
根据定义,继承是一种机制,其中一个对象充当另一个对象的基础,并保留其所有对象属性。
因此,如果B类继承自A类,那么A类的每个特征也将在B类中提供。A类将是“基类”,B类将是“派生类”。
当你有几个共享相同功能的类时,这很方便。
基本语法:
class Base: pass
class Derived(Base): pass
A more forged example:
class Animal:
def __init__(self):
print("and I'm alive!")
def eat(self, food):
print("ñom ñom ñom", food)
class Human(Animal):
def __init__(self, name):
print('My name is ', name)
super().__init__()
def write_poem(self):
print('Foo bar bar foo foo bar!')
class Dog(Animal):
def __init__(self, name):
print('My name is', name)
super().__init__()
def bark(self):
print('woof woof')
michael = Human('Michael')
michael.eat('Spam')
michael.write_poem()
bruno = Dog('Bruno')
bruno.eat('bone')
bruno.bark()
>>> My name is Michael
>>> and I'm alive!
>>> ñom ñom ñom Spam
>>> Foo bar bar foo foo bar!
>>> My name is Bruno
>>> and I'm alive!
>>> ñom ñom ñom bone
>>> woof woof
调用super()会调用Base方法,因此,调用super().__init__() 就是调用 Animal__init__。
有一个称为 MetaClasses 的更高级的python功能,可帮助程序员直接控制类的创建。
# 请注意,你通常不需要了解编译过程,而只需知道一切都来自哪里
# 并给出完整的答案表明你真正知道你在说什么。
通常,每个编译过程都有两个步骤。
- 分析
- 产生代码.
Analysis can be broken into:
1. 词法分析 (标记源代码)
2. 语法分析 (如果语法正确,请检查标记是否合法,tldr)
for i in 'foo'
^
SyntaxError: invalid syntax
We missed ':'
3. 语义分析 (上下文分析,合法语法仍然会触发错误,你是否尝试过除以0,哈希可变对象或使用未声明的函数?)
1/0
ZeroDivisionError: division by zero
这三个分析步骤负责错误处理。
第二步将负责错误,主要是语法错误,这是最常见的错误。
第三步将负责异常。
如我们所见,异常是语义错误,有许多内置的异常:
ImportError
ValueError
KeyError
FileNotFoundError
IndentationError
IndexError
...
你还可以具有用户定义的异常,这些异常必须直接或间接地从Exception类继承。
常见例子:
class DividedBy2Error(Exception):
def __init__(self, message):
self.message = message
def division(dividend,divisor):
if divisor == 2:
raise DividedBy2Error('I dont want you to divide by 2!')
return dividend / divisor
division(100, 2)
>>> __main__.DividedBy2Error: I dont want you to divide by 2!
最简单的是 str[::-1] 但不是效率最高的.
"经典" 方式:
foo = ''
for char in 'pizza':
foo = char + foo
>> 'azzip'
首先,你询问用户要使用的数字量。 使用while循环,每个循环将amount_of_numbers减1,直到amount_of_numbers变为0。 在while循环中,你想询问用户一个数字,该数字将在每次循环运行时添加一个变量。
def return_sum():
amount_of_numbers = int(input("How many numbers? "))
total_sum = 0
while amount_of_numbers != 0:
num = int(input("Input a number. "))
total_sum += num
amount_of_numbers -= 1
return total_sum
with open('file.txt', 'w') as file:
file.write("My insightful comment")
使用 re 模式
li = [[1, 4], [2, 1], [3, 9], [4, 2], [4, 5]]
sorted(x, key=lambda l: l[1])
[{'name': 'Mario', 'food': ['mushrooms', 'goombas']}, {'name': 'Luigi', 'food': ['mushrooms', 'turtles']}]
获取所有的食物类型,最后输出: {'mushrooms', 'goombas', 'turtles'}brothers_menu = \
[{'name': 'Mario', 'food': ['mushrooms', 'goombas']}, {'name': 'Luigi', 'food': ['mushrooms', 'turtles']}]
# "经典" 方式
def get_food(brothers_menu) -> set:
temp = []
for brother in brothers_menu:
for food in brother['food']:
temp.append(food)
return set(temp)
# 一直先行方式 (Using list comprehension)
set([food for bro in x for food in bro['food']])
最简短的方式是: my_string[::-1]
但是这不是效率最高的.
经典方式是:
def reverse_string(string):
temp = ""
for char in string:
temp = char + temp
return temp
return
返回什么?access
, search
insert
and remove
下面的数据结构:负责抓取存储数据的Prometheus服务器推送网关用于短期作业警报管理负责警报 ;)
git pull
和 git fetch
的区别是什么?简单来说, git pull = git fetch + git merge
当你运行git pull时,它会从远程或中央获取所有更改
存储库,并将其附加到本地存储库中的相应分支。
git fetch从远程存储库获取所有更改,将更改存储在
本地存储库中的单独分支
git 目录
, 工作目录
和 暂存区
Git目录是Git存储项目的元数据和对象数据库的地方。 这是Git最重要的部分,当你从另一台计算机克隆存储库时,它就是复制的。
工作目录是项目一个版本的单个签出。 这些文件将从Git目录中的压缩数据库中拉出,并放置在磁盘上供你使用或修改。
暂存区是一个简单文件,通常包含在你的Git目录中,用于存储有关下一次提交的内容的信息。 有时称为索引,但将其称为暂存区已成为标准。
答案来自 git-scm.com
首先,打开有冲突的文件,然后确定有什么冲突。
接下来,根据你的公司或团队接受的是什么,你可以与自己的
同事解决冲突或自行解决
解决冲突后,使用 git add
git reset
和 git revert
区别是什么?
git revert
创建一个新的提交,撤消上一次提交的更改。
git reset
根据使用情况,可以修改索引或更改分支头当前指向的提交。
使用 git rebase>
命令
git rebase
?提及两个或三个就足够了,最好提到“递归”作为默认值。
recursive
resolve
ours
theirs
这篇文章解释是最好的: https://git-scm.com/docs/merge-strategies
git diff
git checkout HEAD~1 -- /path/of/the/file
也许不错,它是:
有一篇文章关于 Octopus merge: http://www.freblogg.com/2016/12/git-octopus-merge.html
Go 而且有一个很好的社区.
var x int = 2
和 x := 2
区别是什么?结果相同,变量值为2。
with var x int = 2
we are setting the variable type to integer while with x := 2
we are letting Go figure out by itself the type.
错. 我们不能重新声明变量,必须使用声明的变量。
应该根据你的使用情况回答此问题,一些示例是:
func main() {
var x float32 = 13.5
var y int
y = x
}
package main
import "fmt"
func main() {
var x int = 101
var y string
y = string(x)
fmt.Println(y)
}
它看起来在101处设置了什么unicode值,并将其用于将整数转换为字符串。
如果要获取“ 101”,则应使用“ strconv” 软件包,然后替换 y = string(x)
with y = strconv.Itoa(x)
package main
func main() {
var x = 2
var y = 3
const someConst = x + y
}
package main
import "fmt"
const (
x = iota
y = iota
)
const z = iota
func main() {
fmt.Printf("%v\n", x)
fmt.Printf("%v\n", y)
fmt.Printf("%v\n", z)
}
package main
import "fmt"
const (
_ = iota + 3
x
)
func main() {
fmt.Printf("%v\n", x)
}
主要区别在于SQL数据库是结构化的(数据以带有行和列的表格-像是Excel电子表格表格),而NoSQL是
非结构化的,并且数据存储会根据NoSQL DB的设置方式而有所不同,例如
作为键值对,面向文档等
db.books.find({"name": /abc/})
db.books.find().sort({x:1})
#!/bin/bash
取决于所使用的语言和设置,例如在Bash中,默认情况下,脚本将继续运行。
echo $0
echo $?
echo $$
echo $@
echo $#
continue
和 break
. 你什么时候使用它们?😦){ 😐:& };:
使用 if/else 的一种简短方法。 一个例子:
[[ $a = 1 ]] && b=“yes, equal” || b=“nope”
Structured Query Language(结构化查询语言)
主要区别在于SQL数据库是结构化的(数据以
带有行和列的表格-像是Excel电子表格表格),而NoSQL是
非结构化的,并且数据存储会根据NoSQL DB的设置方式而有所不同,例如
作为键值对,面向文档等
ACID代表原子性,一致性,隔离性,耐久性。为了符合ACID,数据库必须满足四个标准中的每个标准
原子性 - 数据库发生更改时,它整体上应该成功或失败。
例如,如果你要更新表,则更新应完全执行。如果仅部分执行,则
更新被视为整体失败,并且不会通过-数据库将恢复为原始状态
更新发生之前的状态。还应该提到的是,原子性确保每个
事务以其自身的独立“单元”完成 - 如果任何部分失败,则整个语句都会失败。
一致性 - 对数据库所做的任何更改都应将其从一种有效状态转变为另一种有效状态。
例如,如果你对数据库进行了更改,则不应破坏它。通过检查和约束来保持一致性
在数据库中预定义。例如,如果你尝试将列的值从字符串更改为int
应该是数据类型字符串,一致的数据库将不允许该事务通过,并且该操作将
不执行
隔离 - 确保数据库不会被“更新中”-因为多个事务正在运行
同时,它仍应保持数据库处于与按顺序运行事务相同的状态。
例如,假设有20个人同时对数据库进行了更改。在
当你执行查询时,已完成20项更改中的15项,但仍有5项正在进行中。你应该
仅看到已完成的15个更改 - 随着更改的进行,你将看不到数据库的更新中。
耐用性 - 更改一旦提交,无论发生什么情况都将保持提交状态
(电源故障,系统崩溃等)。这意味着所有已完成的交易
必须记录在非挥发性内存中。
请注意,SQL本质上符合ACID。某些NoSQL DB可能符合ACID,具体取决于
它们的工作方式,但是根据一般经验,NoSQL DB不被视为符合ACID
SQL - 当数据完整性至关重要时,最适合使用。 由于符合ACID,SQL通常由许多业务实现特别是金融领域。
NoSQL - 非常适合你需要快速扩展的情况。 请记住NoSQL是为Web应用程序设计的
,如果你需要快速将相同信息散布到多台服务器,它将会很好的用
此外,由于 NoSQL 不遵守具有列和行结构的严格表
关系数据库所要求的,你可以将不同的数据类型存储在一起。
笛卡尔积是指第一个表中的所有行都与第二个表中的所有行连接在一起时的结果
表。 这可以通过不定义要联接的键来隐式完成,也可以通过以下方式显式地完成:
在两个表上调用CROSS JOIN,如下所示:
Select * from customers CROSS JOIN orders;
请注意,笛卡尔积也可能是一件坏事 - 执行联接时
在两个都没有唯一键的表上,这可能会导致返回信息
是不正确的。
对于这些问题,我们将使用下面显示的“客户和订单”表:
Customers
Customer_ID | Customer_Name | Items_in_cart | Cash_spent_to_Date |
---|---|---|---|
100204 | John Smith | 0 | 20.00 |
100205 | Jane Smith | 3 | 40.00 |
100206 | Bobby Frank | 1 | 100.20 |
ORDERS
Customer_ID | Order_ID | Item | Price | Date_sold |
---|---|---|---|---|
100206 | A123 | Rubber Ducky | 2.20 | 2019-09-18 |
100206 | A123 | Bubble Bath | 8.00 | 2019-09-18 |
100206 | Q987 | 80-Pack TP | 90.00 | 2019-09-20 |
100205 | Z001 | Cat Food - Tuna Fish | 10.00 | 2019-08-05 |
100205 | Z001 | Cat Food - Chicken | 10.00 | 2019-08-05 |
100205 | Z001 | Cat Food - Beef | 10.00 | 2019-08-05 |
100205 | Z001 | Cat Food - Kitty quesadilla | 10.00 | 2019-08-05 |
100204 | X202 | Coffee | 20.00 | 2019-04-29 |
Select *
From Customers;
Select Items_in_cart
From Customers
Where Customer_Name = “John Smith”;
Select SUM(Cash_spent_to_Date) as SUM_CASH
From Customers;
Select count(1) as Number_of_People_w_items
From Customers
where Items_in_cart > 0;
你可以加入他们的唯一键。 在这种情况下,唯一键为中的Customer_ID
客户表和订单表
Select c.Customer_Name, o.Item
From Customers c
Left Join Orders o
On c.Customer_ID = o.Customer_ID;
with cat_food as (
Select Customer_ID, SUM(Price) as TOTAL_PRICE
From Orders
Where Item like “%Cat Food%”
Group by Customer_ID
)
Select Customer_name, TOTAL_PRICE
From Customers c
Inner JOIN cat_food f
ON c.Customer_ID = f.Customer_ID
where c.Customer_ID in (Select Customer_ID from cat_food);
尽管这是一个简单的声明,但“ with”子句在
在连接到另一个表之前,需要在一个表上运行一个复杂的查询。 用语句很好,
因为你在运行查询时会创建一个伪临时文件,而不是创建一个新表。
目前尚无法获得所有猫粮的总和,因此我们使用了with语句来创建
伪表检索每个客户花费的价格总和,然后正常加入该表。
方案是没有口头回答的问题,需要你满足以下条件之一:
这些问题通常作为应聘者的一项家庭任务作为候选,可以将多个主题结合在一起。
在下面,你可以找到一些场景问题: