Ubuntu iptables

Ubuntu 编写的 iptables 规则,在重启后会失效;使用 iptables-persistent 持久化保存。

1
sudo apt install iptables-persistent

编写完规则后,执行:

1
2
3
sudo netfilter-persistent save

sudo netfilter-persistent reload

参考 :

1、ubuntu/debian iptables规则持久化,iptables-persistent

2、 https://help.ubuntu.com/community/IptablesHowTo#Solution_.233_iptables-persistent

添加防火墙过滤规则步骤如下;

1、查看现有防火墙过滤规则:

iptables -nvL --line-number

2、添加防火墙过滤规则(设置白名单):

   1)添加白名单

        iptables -I INPUT 3 -s 136.6.231.163 -p tcp --dport 1521 -j ACCEPT

        命令详解:

            -I:添加规则的参数  

                INPUT:表示外部主机访问内部资源

                3:表示添加到第三行(可以任意修改)

            -s:指定作为源地址匹配,这里不能指定主机名称,必须是IP;

            -p: 用于匹配协议的(这里的协议通常有3种,TCP/UDP/ICMP)

                --dport: 用于匹配端口号

            -j: 用于匹配处理方式:

                常用的ACTION:


             DROP:悄悄丢弃
	        一般我们多用DROP来隐藏我们的身份,以及隐藏我们的链表
             REJECT:明示拒绝
             ACCEPT:接受
    2)查看添加结果

        iptables -nvL --line-number

原文链接:https://blog.csdn.net/qq_37837701/java/article/details/80578807

https://blog.csdn.net/sanve/article/details/80881380

IP地址网段表示法](https://www.cnblogs.com/amyzhu/p/11396136.html)

172.12.34.0/25

  1. 子网掩码:用于表示IP地址中的多少位用来做主机号。因为”其中值为1的比特留给网络号和子网号,为0的比特留给主机号”(TCP/IP V1)。
  2. 172.12.34.0/25含义:
    1. 172.12.34.0——表示一个子网号
    2. 25——表示采用子网掩码中国呢的前25位为有效未,即用 32-25=7big 来表示主机号,该子网可以容纳 2^7-2=126台主机。
    3. 因此172.12.34.0/25 表示IP范围为 172.12.34.1~172.12.34.126

https://blog.csdn.net/csfreebird/article/details/8132362

JSON-LD

什么是JSON-LD?

JSON-LD是 JavaScript Object Notation for Linked Data的缩写,是一种基于JSON表示和传输互联数据(Linked Data)的方法。可用于实施结构化数据。JSON-LD描述了如何通过JSON表示有向图,以及如何在一个文档中混合表示互联数据及非互联数据。JSON-LD的语法和JSON兼容。基于JSON-LD可以在基于Web的编程环境中使用互联数据,构造可互操作的互联数据Web服务(linked data web services),并向基于JSON的存储引擎中保存互联数据。

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,适合于服务器与JavaScript之间交换数据。对于JSON我们非常熟悉,但对于互联数据这个词,可能部分人会既熟悉而又觉得陌生,因为单字面意思已经很清楚,但要表达出其完整含义也并不容易。

互联数据可以说是语义网(Semantic Web)的一部分,但相较于1998年语义网概念的提出,互联数据这个一样显而易见的概念实际出现却要晚了数年。这些年我们一直在强调Web的语义,即便是HTML5那一堆新增标签也不外如是。语义并不是简单的将数据放到Web上,而是对于不仅仅是人,机器也必须都能识别并准确的处理以及高效的利用。而互联数据则更要求数据的指向性,当我们有部分数据时,即可找到对应的相关联的其他数据。当数据从数据库里被拼装成页面后,可能对于人而言找到数据可能轻而易举,但对于机器而言,很难将页面恢复到原始数据,也缺乏语义的判断。若无标准来统一语义和数据互联,对于机器来说整个Web其实是乱糟糟的。

为了使机器可以准确理解,处理和整合数据,我们有了语义Web。而其组成部分RDF(Resource Description Framework)即是用于描述网络资源的W3C标准。它使得语义Web技术相关的技术更加简单、不复杂以及面向一般开发人员。另外,与JSON-LD相似的RDFa(通过属性嵌入RDF),同样是提供上下文,但属性嵌入到方式注定RDFa只适合小范围的片段嵌入以代替Mircodata,而难以用作大量纯粹数据的定义方式。而添加RDFa的难度也往往大于JSON-LD,毕竟是需要去接受已经存在的内容的情况。RDF工作组目前已经停止了活动,但通过艰苦的努力,已经将JSON-LD 1.0JSON-LD 1.0处理算法和API推进到了W3C的标准状态。

怎样使用JSON-LD?

JSON-LD处理算法和API(JSON-LD Processing Algorithms and API)描述了处理JSON-LD数据所需的算法及编程接口,通过这些接口可以在JavaScript, Python及Ruby等编程环境中直接对JSON-LD文档进行转换和处理。

下面是一个直接选自规范的例子:

1
2
3
4
5
{
"name": "Manu Sporny",
"homepage": "http://manu.sporny.org/",
"image": "http://manu.sporny.org/images/manu.png"
}

这个JSON文档表示一个人。人们很容易推断这里的语义:“name”是人的名字,“homepage”是其主页,“image”是其某种照片。然而机器不理解“name”和“image”这样的术语。

为解决该问题,我们可以使用链接数据。下面使用JSON-LD表示上面的例子:

1
2
3
4
5
{
"http://schema.org/name": "Manu Sporny",
"http://schema.org/url": { "@id": "http://manu.sporny.org/" },
"http://schema.org/image": { "@id": "http://manu.sporny.org/images/manu.png" }
}

通过链接到schema.org上的定义,我们可以教给机器如何理解“name”、“url”和“image”的语义。不过有点复杂了。通过JSON-LD所谓的“上下文(context)”,我们可以兼顾第一个例子的简洁性和第二个例子的语义理解。基于第一个例子,我们引入一个context:

1
2
3
4
5
6
{
"@context": "http://json-ld.org/contexts/person.jsonld",
"name": "Manu Sporny",
"homepage": "http://manu.sporny.org/",
"image": "http://manu.sporny.org/images/manu.png"
}

我们现在链接到了json-ld.org上的一个context。context文档看上去像下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"@context":
{
"name": "http://schema.org/name",
"image": {
"@id": "http://schema.org/image"
"@type": "@id"
},
"homepage": {
"@id": "http://schema.org/url",
"@type": "@id"
}
}
}

这种方法的另一个优点是,多个文档可以使用同一个context。

参考资料:

https://www.biaodianfu.com/json-ld.html

https://github.com/Webnuvola/laravel-json-ld

MinIO

参考:官方文档

安装

Ubuntu 可以直接下载执行文件

1
2
3
4
5
sudo wget https://dl.minio.io/server/minio/release/linux-amd64/minio -O /opt/minio
sudo chmod +x /opt/minio
sudo ln -s /opt/minio /usr/bin/

minio --help

创建文件夹

1
2
3
4
#配置文件
sudo mkdir /etc/minio
#存放文件
sudo mkdir /var/www/minio

使用下面的命令运行,使用输出的 AccessKey / SecretKey 登录,配置文件是 /etc/minio/config.json, AccessKey / SecretKey 会在里面保存,上传的文件会保存在 /var/www/minio 里。

1
/usr/bin/minio --config-dir /etc/minio/ server /var/www/minio

这时可以访问 网站 IP:9000 打开 Minio 的网页管理。

设置 Nginx

使用域名进行访问,可以在 Nginx 的配置文件中加入下面的内容:

1
2
3
4
location / {
proxy_set_header Host $http_host;
proxy_pass http://localhost:9000;
}

这时访问网站就会直接访问 Minio 的网页了。可以在 Minio 执行命令中加入 --address "127.0.0.1:9000", 这样只会 Minio 只会监听本机地址。

1
/usr/bin/minio --config-dir /etc/minio/ server --address "127.0.0.1:9000" /var/www/minio

设置 Systemd 服务

处理文件夹权限

1
2
sudo chown -R www-data:www-data /etc/minio
sudo chown -R www-data:www-data /var/www/minio

创建 /etc/systemd/system/minio.service 文件

1
2
3
4
5
6
7
8
[Unit]
Description=minio_backend
After=network.target
[Service]
User=www-data
ExecStart=/usr/bin/minio --config-dir /etc/minio/ server --address "127.0.0.1:9000" /var/www/minio
[Install]
WantedBy=multi-user.target

载入并启动服务

1
2
3
4
5
6
7
8
9
10
sudo systemctl daemon-reload
# 启动
sudo systemctl start minio
# 查看状态
sudo systemctl status minio
# 开机启动
sudo systemctl enable minio

# 查看输出
sudo journalctl -u minio

https://homulilly.com/post/use-minio.html

使用:

https://blog.csdn.net/qq_39159076/article/details/100578724

Ubuntu 安装 PHP 的 PDO_OCI 扩展

已经用 apt 安装了 php7.3-cli,php7.3-fpm,php7.3-dev 等。
安装了 Oracle 的 Instant Client(可参考:https://hefengbao.github.io/helloword/ubuntu-install-oracle-instant-client-and-oci-20180511/ ),现在安装 pdo_oci, 貌似只能通过源码安装:

下载 php 源码

wget https://www.php.net/distributions/php-7.3.16.tar.xz

1
2
3
4
tar -xvf php-7.3.16.tar.xz

cd php-7.3.16/ext/pdo_oci/

phpize

1
/usr/bin/phpize7.3

结果如下:
Configuring for:
PHP Api Version: 20180731
Zend Module Api No: 20180731
Zend Extension Api No: 320180731

1
./configure --with-pdo-oci=instantclient,/usr/lib/oracle/19.5/client64/lib --with-oci8=instantclient,/usr/lib/oracle/19.5/client64/lib -with-php-config=/usr/bin/php-config7.3
1
2
3
sudo make

sudo make install

结果如下:
Installing shared extensions: /usr/lib/php/20180731/

extension=pdo_oci 添加到 /etc/php/7.3/cli/php.ini/etc/php/7.3/fpm/php.ini

php -m 查看。

参考:

https://www.fujieace.com/php/php-extensions/config-m4.html
https://blog.csdn.net/Zhang_Ying_Jie/article/details/79315022
https://blogs.oracle.com/opal/updated-php-72-pdo_oci-install-configure-syntax

Using Scoped Functions in Kotlin - let, run, with, also, apply

Scoped Functions in Kotlin

By definition, Scoped functions are functions that execute a block of code within the context of an object.

Well, what does this mean? These functions provide a way to give temporary scope to the object under consideration where specific operations can be applied to the object within the block of code, thereby, resulting in a clean and concise code. Not clear still right? Yeah. In Software Development, things are only better understood by implementing rather than reading. So, let’s go ahead and understand these scoped functions with some examples.

The context of the object can be referred to as “it” or “this” which we will be understanding through examples in this article.

Differentiating scoped functions with examples

There are five scoped functions in Kotlin: let, run, with, also and *apply.* Let’s go through them one by one.

But before going through these examples, let’s consider a Model class “Person”

1
2
3
4
5
6
7
8
9
class Person() {
var name: String = "Abcd"
var contactNumber: String = "1234567890"
var address: String = "xyz"
fun displayInfo() = print("\n Name: $name\n " +
"Contact Number: $contactNumber\n " +
"Address: $address")

}

let

Let’s consider the following function:

1
2
3
4
5
6
7
8
private fun performLetOperation() {
val person = Person().let {
return@let "The name of the Person is: ${it.name}"
}
print(person)
}
output:
The name of the Person is: Abcd

From the above code snippet, we can see that although “let” operation is performed on a Person object, the output of the code is a string value and not the Person object. This implies that the “let” operator provides an option to perform an operation on the current object and return any value based on the use case.

Note: It is not necessary to write “return@let”. This is only done to enhance code readability. In Kotlin, if the last statement in a “let” block is a non-assignment statement, it is by default a return statement. For example:

1
2
3
4
5
6
7
8
private fun performLetOperation() {
val person = Person().let {
"The name of the Person is: ${it.name}"
}
print(person)
}
output:
The name of the Person is: Abcd

The above code also behaves the same way since the last statement is a non-assignment statement. So what happens if we don’t return anything in the “let” block? It is similar to calling a function that has no return value. So let’s say if we modify the function as:

1
2
3
4
5
6
7
8
private fun performLetOperation() {
val person = Person().let {
it.name = "NewName"
}
print(person)
}
output:
kotlin.Unit

We can see that since there was no return value in the let block and hence printing the same would indicate that the “print” functionality is called upon a unit function.

There are other advantages of using let:

  • It refers to the context of the object by using the “it” keyword and hence, this “it” can be renamed to a readable lambda parameter.
1
2
3
4
5
6
private fun performLetOperation() {
val person = Person().let { personDetails ->
personDetails.name = "NewName"
}
print(person)
}

This can be very helpful if we have nested let blocks, and since all let blocks refer to the context of their respective objects as “it”, it might be difficult for the compiler which objects we are referring to:

  • The second advantage is it easily helps in providing null checks. Let’s say we make the “name” parameter of the “Person” class nullable and we want to print the name of the person only if it is a not null value, then we can write a clean, simple and concise code as follows:
1
2
3
4
5
6
7
var name: String? = "Abcd"
private fun performLetOperation() {
val name = Person().name?.let {
"The name of the Person is: $it"
}
print(name)
}

We Know how lengthy the code would be to perform a null check in Java. Well, that’s the beauty of kotlin!

let” can also be used when we want to perform an operation on the result of a call chain. Let’s take the following example:

1
2
3
4
5
fun main() { 
val numbers = mutableListOf("One","Two","Three","Four","Five")
val resultsList = numbers.map { it.length }.filter { it > 3 }
print(resultsList)
}

So our aim is to fetch the values in the ArrayList whose length is greater than 3. Since we had to print the result we stored the result in a separate variable and then printed it. But using “let” operator, we can modify the code as:

1
2
3
4
5
6
fun main() {
val numbers = mutableListOf("One","Two","Three","Four","Five")
numbers.map { it.length }.filter { it > 3 }.let {
print(it)
}
}

This way we can perform an operation on the result of the call chain.

run

The “run” operator is similar to the “let” operator in terms of accepting a return value that is different from the object on which the scope function is being applied to. Hence, a “run” operator can be used to initialize an object and return the result of it.

1
2
3
4
5
6
7
8
9
10
11
private fun performRunOperation() {
Person().run {
name = "Asdf"
contactNumber = "0987654321"
return@run "The details of the Person is: ${displayInfo()}"
}
}
output:
Name: Asdf
Contact Number: 0987654321
Address: xyz

run vs let

So if run is similar to let in terms of accepting any return value, what’s the difference? The difference is run refers to the context of the object as “this” and not “it”. That is the reason we did not use “${this.name}” as it would be redundant here since the block of code understands that “name” is used here concerning the Person object.

One point here is that since the context is referred to as “this”, it cannot be renamed to a readable lambda parameter. So depending on the use case and requirement we have to choose between the let and the run operator. The “run” operator also helps in easy null checks similar to the “let” operator

1
2
3
4
5
6
7
8
9
var name: String? = "Abcd"
private fun performRunOperation() {
val name = Person().name?.run {
"The name of the Person is: $this"
}
print(name)
}
Output:
The name of the Person is: Abcd

with

The “with” operator is completely similar to the run operator that we just discussed. It also refers to the context of the object as “this”, similar to how the “run” operator uses it.

1
2
3
4
5
6
7
8
private fun performWithOperation() {
val person = with(Person()) {
return@with "The name of the Person is: ${this.name}"
}
print(person)
}
Output:
The name of the Person is: Abcd

with vs run

So, if “with” is the same as “run”, what’s the difference? How should we choose between these two? Now, this is an interesting case. Let’s consider a case where a Person object can be nullable.

we can see that the context of the object referred to as “this” is a nullable type of Person. And hence, to correct this, we need to change the code as:

1
2
3
4
5
6
7
8
9
private fun performWithOperation() {
val person: Person? = null
with(person) {
this?.name = "asdf"
this?.contactNumber = "1234"
this?.address = "wasd"
this?.displayInfo()
}
}

So performing a null check using a “with” operator is difficult and this is where we can replace it with “run” as follows:

1
2
3
4
5
6
7
8
9
private fun performRunOperation() {
val person: Person? = null
person?.run {
name = "asdf"
contactNumber = "1234"
address = "wasd"
displayInfo()
}
}

This looks a lot cleaner.

apply

The apply function is similar to the run functionality only in terms of referring to the context of the object as “this” and not “it” and also in providing null safety checks:

1
2
3
4
5
6
7
8
9
private fun performApplyOperation() {
val person: Person? = null
person?.apply {
name = "asdf"
contactNumber = "1234"
address = "wasd"
displayInfo()
}
}

“apply” use-case in Android Development

Specifically for Android Development, “apply“ can be useful in many cases. We have many scenarios where we should return an instance of Intent or an Alert Dialog etc., by adding specific attributes to them. Let’s take the example of an intent here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Normal approach
fun createIntent(intentData: String, intentAction: String): Intent {
val intent = Intent()
intent.action = intentAction
intent.data = Uri.parse(intentData)
return intent
}

// Improved approach, by using apply
fun createIntent(intentData: String, intentAction: String) =
Intent().apply {
action = intentAction
data = Uri.parse(intentData)
}

The improved approach from the above code snippet helps in avoiding variable name redundancy thereby enhancing the code readability and the principle of clean code.

apply vs run

So let’s see the difference between apply and run functions.

We can see that run accepts a return statement whereas **“**apply” does not accept a return statement(we can see the error thrown by the IDE in the image) and always returns the same object which it is referring to.

also

The “*also”* function is similar to the *let* functionality only in terms of referring to the context of the object as “it” and not “this” and also in providing null safety checks:

1
2
3
4
5
6
7
8
9
10
11
12
private fun performAlsoOperation() {
val name = Person().also { currentPerson ->
print("Current name is: ${currentPerson.name}\n")
currentPerson.name = "modifiedName"
}.run {
"Modified name is: $name\n"
}
print(name)
}
output:
Current name is: Abcd
Modified name is: modifiedName

Here we can see the usage of the readable lambda parameters, similar to what we have seen in the “let” operator case. The advantage of using “also” operator is that while doing a chain of operations, this operator helps in evaluating the current operating value if required. Let’s suppose we did not use the “also” operator in the above case, we should have written the code as:

1
2
3
4
5
6
7
var name = Person().name
print("Current name is: $name\n")
name = "modifiedName"
name = name.run {
"Modified name is: $name\n"
}
print(name)

Although this gives the same output, the chain in which the operations are being held is broken and that would not make a good readable code and hence “also” operator is very useful in this case. Hence, by using the also operator, the code can be modified as:

1
2
3
4
5
6
7
8
9
private fun performAlsoOperation() {
val name = Person().also {
print("Current name is: ${it.name}\n")
it.name = "ModifiedName"
}.run {
"Modified name is: $name\n"
}
print(name)
}

This way we can execute the intermediate result within the execution chain without breaking the chain, thereby leading to a better readable code.

“also” vs “let”

So let’s see the difference between also and let functions.

We can see that let accepts a return statement whereas “also” does not accept a return statement(we can see the error thrown by the IDE in the image) and always returns the same object which it is referring to.

Summary

We can also represent the summary of choosing between the scoped functions as a flowchart.

That’s all about the Scoped functions in Kotlin. Although we might be using this in our code, we hope that our article has given you a clearer way of understanding and implementing the right scoped function in the right place.

来源:

https://blog.mindorks.com/using-scoped-functions-in-kotlin-let-run-with-also-apply

phpmyadmin 连接 mysql 8

phpmyadmin 连接 mysql 8 数据库,出现如下错误:

1
2
mysqli_real_connect(): The server requested authentication method unknown to the client [caching_sha2_password]
mysqli_real_connect(): (HY000/2054): The server requested authentication method unknown to the client

安装 php7.4, 或者按网上的方法,修改 mysql 的加密方式。

How to enable logging in OkHttp ?

Ever had some bad issues, while doing an API call in your android application? Or may be got some error which was making your API call unsuccessful.

What did you try?

First resort would have been to try API calls through some client that what was the error. Or may be something else you would have tried.

What if I told you that you could have chosen something else as well and that would have not required you to test APIs via some client.

You can use Interceptors in your android code to gets the logs their itself while getting an error. This sounds a better solution right?

Let’s understand more about logging in Android. So, in this, we will discuss about okhttp logging interceptor and how we can leverage it log our API calls.

What is OkHttp?

OkHttp is an interceptor which helps you to log your API calls. So, here an interceptor is more like a manager for an API call which helps you to monitor or perform certain action on your API calls.

Let us start by including it in our project, we will add the following in the build.gradle file:

1
implementation "com.squareup.okhttp3:logging-interceptor:4.0.1"

and to start logging your API calls, we need to first make an API call,

1
2
3
4
val client = OkHttpClient.Builder()
var request = Request.Builder()
.url(/** YOUR API URL **/)
.build()

Here, we create object for request and declared a variable client of OkHttpClient. Now, to perform API call, we will use the following to do it,

1
2
3
4
5
6
7
8
9
10
client.newCall(request).enqueue(object :Callback{
override fun onFailure(request: Request?, e: IOException?) {
//API Call fails
}

override fun onResponse(response: Response?) {
//Do something with response
}

})

Now, we have performed the first API call. But here we would not see any logs coming up because we have not added any specific interceptor to log the calls. So, how can we log the response the call.

To, start logging we need to add interceptors in the above OkHttpClient.

And as we mentioned , interceptors are used to monitor the API call and it will print the logs which would get generated, in the Logcat of the console.

To add a Interceptor,

1
2
val logging = HttpLoggingInterceptor()
logging.level = (HttpLoggingInterceptor.Level.BASIC)

we create and variable called logging of HttpLoggingInterceptor and set the level of logging to *Basic.* Basic is the initial level in which you can just log reqest and the response of the API. We can also have NONE, HEADERS and BODY.

*NONE : Logs Nothing.*

*HEADERS : Logs Request and Response along with Header.*

*BODY : Logs Request and Response along with header and if body present in the API call.*

And, to add this interceptor to the client we use,

1
2
val client = OkHttpClient.Builder()
client.addInterceptor(logging)

and, now when we call the API again we would start seeing the logs getting logged in the Logcat like the following,

1
2
3
--> POST /greeting http/1.1 (3-byte body)

<-- 200 OK (22ms, 6-byte body)

NOTE :

\1. To add a custom TAG for your or logs to get generated, just add the following,

1
2
3
4
5
val logging = HttpLoggingInterceptor(object : Logger() {
fun log(message: String) {
Log.d("YOUR TAG", message)
}
})

and you will see the logs getting generated with the TAG you added.

\2. You can also create a custom Interceptor by extending the Interceptor class.

1
2
3
4
5
6
7
8
class CustomInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
request = request.newBuilder()
.build()
return chain.proceed(request)
}
}

and add it to the client using,

1
2
val client = OkHttpClient.Builder()
client.addInterceptor(CustomInterceptor())

\3. To hide sensative information from the Logcat of Android we can use,

1
2
logging.redactHeader("Authorization")
logging.redactHeader("Cookie")

Here, in above snippet redactHeader hides the sensitive information of Authorization and Cookie key.

These gets generated only in HEADERS and BODY level.

This is how we can log API calls being made in your Android application.