ubuntu 20.04配置samba

$ sudo apt-get install libcanberra-gtk-module

$ sudo apt install avahi-daemon

$ sudo apt-get remove --purge samba

$ sudo apt-get install samba

编辑配置文件

$ sudo vim /etc/samba/smb.conf

文件尾部增加

[Movie]
   comment = Movie
   path = /mnt/data/Movie/ # 需要共享的目录位置
   browseable = yes # 是否可见
   read only = yes # 是否只读
   guest ok = yes # 登陆用户是否可访问
   valid users = user # 可访问的用户

重启服务

$ sudo service smbd restart

参考链接


聊聊如何从SVN迁移源码到Git仓库

背景介绍

这里就不再赘述关于SVN与Git的区别以及为什么要迁移源码到Git了,毕竟Git是当前的主流DVCS了,而且已经公认地非常好用,如果你还在使用SVN的话该考虑换了,是时候迁移那些遗留代码了,有兴趣可以参阅 Why Git 和 Perforce to Git 了解更多。

通常来说,在项目开发过程中,难免会遇到一些老项目代码正被SVN管理着,但基于当下诸多原因,或是扩展开发,或是战略转移,或是为了更好地开发体验,需要将这些在维护的遗留项目源码迁移为Git管理。

那如何有效地迁移源码?并且如何保留提交记录、分支记录以及开发成员等信息呢?笔者前一段时间就经历了这样的迁移工作,还是有必要分享一下,也算是一种总结了。

继续阅读聊聊如何从SVN迁移源码到Git仓库

解决okHttp不能自动缓存header cookies里的sessionid

由于app要实现登录缓存功能,但惊讶的发现不经过设置okHttp是不会自动管理header的.

官网的文档也是醉了,找了半天没看懂怎么搞.

其实实现自动管理cookie很简单很简单,在OkHttp的builder中加上个.cookiejar()就能实现自动缓存,代码如下:

        OkHttpClient.Builder b = new OkHttpClient.Builder();
        b.cookieJar(new CookieJar() {
            //这里一定一定一定是HashMap<String, List<Cookie>>,是String,不是url.
            private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();

            @Override
            public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                cookieStore.put(url.host(), cookies);
            }

            @Override
            public List<Cookie> loadForRequest(HttpUrl url) {
                List<Cookie> cookies = cookieStore.get(url.host());
                return cookies != null ? cookies : new ArrayList<Cookie>();
            }
        });

!!!!!注意注意注意!!!!!!

HashMap的key是String!!!!直接传进去url,是没有效果的!!!!!

参考链接


解决OKHttp不能自动缓存header cookies 里的 sessionid

Android获取设备DNS服务器列表

import android.annotation.TargetApi;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.RouteInfo;
import android.os.Build;
import android.util.Log;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * DNS servers detector
 * <p>
 * IMPORTANT: don't cache the result.
 * <p>
 * Or if you want to cache the result make sure you invalidate the cache
 * on any network change.
 * <p>
 * It is always better to use a new instance of the detector when you need
 * current DNS servers otherwise you may get into troubles because of invalid/changed
 * DNS servers.
 * <p>
 * This class combines various methods and solutions from:
 * Dnsjava http://www.xbill.org/dnsjava/
 * Minidns https://github.com/MiniDNS/minidns
 * <p>
 * Unfortunately both libraries are not aware of Orero changes so new method was added to fix this.
 * <p>
 * Created by Madalin Grigore-Enescu on 2/24/18.
 */

public class DnsServersDetector {

    private static final String TAG = "DnsServersDetector";

    /**
     * Holds some default DNS servers used in case all DNS servers detection methods fail.
     * Can be set to null if you want caller to fail in this situation.
     */
    private static final String[] FACTORY_DNS_SERVERS = {
            "8.8.8.8",
            "8.8.4.4"
    };

    /**
     * Properties delimiter used in exec method of DNS servers detection
     */
    private static final String METHOD_EXEC_PROP_DELIM = "]: [";

    /**
     * Holds context this was created under
     */
    private Context context;

    //region - public //////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Constructor
     */
    public DnsServersDetector(Context context) {
        this.context = context;
    }

    /**
     * Returns android DNS servers used for current connected network
     *
     * @return Dns servers array
     */
    public String[] getServers() {
        // METHOD 1: old deprecated system properties
        String[] result = getServersMethodSystemProperties();
        if (result != null && result.length > 0) {
            return result;
        }
        // METHOD 2 - use connectivity manager
        result = getServersMethodConnectivityManager();
        if (result != null && result.length > 0) {
            return result;
        }
        // LAST METHOD: detect android DNS servers by executing getprop string command in a separate process
        // This method fortunately works in Oreo too but many people may want to avoid exec
        // so it's used only as a failsafe scenario
        result = getServersMethodExec();
        if (result != null && result.length > 0) {
            return result;
        }
        // Fall back on factory DNS servers
        return FACTORY_DNS_SERVERS;
    }

    //endregion

    //region - private /////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Detect android DNS servers by using connectivity manager
     * <p>
     * This method is working in android LOLLIPOP or later
     *
     * @return Dns servers array
     */
    private String[] getServersMethodConnectivityManager() {

        // This code only works on LOLLIPOP and higher
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            try {
                final ArrayList<String> priorityServersArrayList = new ArrayList<>();
                final ArrayList<String> serversArrayList = new ArrayList<>();
                final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(android.content.Context.CONNECTIVITY_SERVICE);
                if (connectivityManager != null) {
                    // Iterate all networks
                    // Notice that android LOLLIPOP or higher allow iterating multiple connected networks of SAME type
                    for (Network network : connectivityManager.getAllNetworks()) {
                        final NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
                        if (networkInfo.isConnected()) {
                            final LinkProperties linkProperties = connectivityManager.getLinkProperties(network);
                            final List<InetAddress> dnsServersList = linkProperties.getDnsServers();
                            // Prioritize the DNS servers for link which have a default route
                            if (linkPropertiesHasDefaultRoute(linkProperties)) {
                                for (InetAddress element : dnsServersList) {
                                    final String dnsHost = element.getHostAddress();
                                    priorityServersArrayList.add(dnsHost);
                                }
                            } else {
                                for (InetAddress element : dnsServersList) {
                                    final String dnsHost = element.getHostAddress();
                                    serversArrayList.add(dnsHost);
                                }
                            }
                        }
                    }
                }

                // Append secondary arrays only if priority is empty
                if (priorityServersArrayList.isEmpty()) {
                    priorityServersArrayList.addAll(serversArrayList);
                }

                // Stop here if we have at least one DNS server
                if (priorityServersArrayList.size() > 0) {
                    return priorityServersArrayList.toArray(new String[0]);
                }
            } catch (Exception ex) {
                Log.d(TAG, "Exception detecting DNS servers using ConnectivityManager method", ex);
            }
        }
        // Failure
        return null;
    }

    /**
     * Detect android DNS servers by using old deprecated system properties
     * <p>
     * This method is NOT working anymore in Android 8.0
     * Official Android documentation state this in the article Android 8.0 Behavior Changes.
     * The system properties net.dns1, net.dns2, net.dns3, and net.dns4 are no longer available,
     * a change that improves privacy on the platform.
     * <p>
     * https://developer.android.com/about/versions/oreo/android-8.0-changes.html#o-pri
     *
     * @return Dns servers array
     */
    private String[] getServersMethodSystemProperties() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            // This originally looked for all lines containing .dns; but
            // http://code.google.com/p/android/issues/detail?id=2207#c73
            // indicates that net.dns* should always be the active nameservers, so
            // we use those.
            final String re1 = "^\\d+(\\.\\d+){3}$";
            final String re2 = "^[0-9a-f]+(:[0-9a-f]*)+:[0-9a-f]+$";
            ArrayList<String> serversArrayList = new ArrayList<>();
            try {
                Class<?> SystemProperties = Class.forName("android.os.SystemProperties");
                Method method = SystemProperties.getMethod("get", new Class[]{String.class});
                final String[] netdns = new String[]{"net.dns1", "net.dns2", "net.dns3", "net.dns4"};
                for (String netdn : netdns) {
                    Object[] args = new Object[]{netdn};
                    String v = (String) method.invoke(null, args);
                    if (v != null && (v.matches(re1) || v.matches(re2)) && !serversArrayList.contains(v)) {
                        serversArrayList.add(v);
                    }
                }

                // Stop here if we have at least one DNS server
                if (serversArrayList.size() > 0) {
                    return serversArrayList.toArray(new String[0]);
                }
            } catch (Exception e) {
                Log.d(TAG, "Exception detecting DNS servers using SystemProperties method", e);
            }
        }
        // Failed
        return null;
    }

    /**
     * Detect android DNS servers by executing getprop string command in a separate process
     * <p>
     * Notice there is an android bug when Runtime.exec() hangs without providing a Process object.
     * This problem is fixed in Jelly Bean (Android 4.1) but not in ICS (4.0.4) and probably it will never be fixed in ICS.
     * https://stackoverflow.com/questions/8688382/runtime-exec-bug-hangs-without-providing-a-process-object/11362081
     *
     * @return Dns servers array
     */
    private String[] getServersMethodExec() {
        // We are on the safe side and avoid any bug
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            try {
                Process process = Runtime.getRuntime().exec("getprop");
                InputStream inputStream = process.getInputStream();
                LineNumberReader lineNumberReader = new LineNumberReader(new InputStreamReader(inputStream));
                Set<String> serversSet = methodExecParseProps(lineNumberReader);
                if (serversSet != null && serversSet.size() > 0) {
                    return serversSet.toArray(new String[0]);
                }
            } catch (Exception e) {
                Log.d(TAG, "Exception in getServersMethodExec", e);
            }
        }
        // Failed
        return null;
    }

    /**
     * Parse properties produced by executing getprop command
     *
     * @param lineNumberReader lineNumberReader
     * @return Set of parsed properties
     * @throws Exception Exception
     */
    private Set<String> methodExecParseProps(BufferedReader lineNumberReader) throws Exception {
        String line;
        Set<String> serversSet = new HashSet<String>(10);
        while ((line = lineNumberReader.readLine()) != null) {
            int split = line.indexOf(METHOD_EXEC_PROP_DELIM);
            if (split == -1) {
                continue;
            }
            String property = line.substring(1, split);

            int valueStart = split + METHOD_EXEC_PROP_DELIM.length();
            int valueEnd = line.length() - 1;
            if (valueEnd < valueStart) {
                // This can happen if a newline sneaks in as the first character of the property value. For example
                // "[propName]: [\n…]".
                Log.d(TAG, "Malformed property detected: \"" + line + '"');
                continue;
            }

            String value = line.substring(valueStart, valueEnd);

            if (value.isEmpty()) {
                continue;
            }

            if (property.endsWith(".dns") || property.endsWith(".dns1") ||
                property.endsWith(".dns2") || property.endsWith(".dns3") ||
                property.endsWith(".dns4")) {

                // normalize the address
                InetAddress ip = InetAddress.getByName(value);
                if (ip == null) continue;
                value = ip.getHostAddress();

                if (value == null) continue;
                if (value.length() == 0) continue;

                serversSet.add(value);
            }
        }
        return serversSet;
    }

    /**
     * Returns true if the specified link properties have any default route
     *
     * @param linkProperties linkProperties
     * @return true if the specified link properties have default route or false otherwise
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private boolean linkPropertiesHasDefaultRoute(LinkProperties linkProperties) {
        for (RouteInfo route : linkProperties.getRoutes()) {
            if (route.isDefaultRoute()) {
                return true;
            }
        }
        return false;
    }
    //endregion
}

参考链接


Android DNS更新与DNS-Prefetch

一、什么是DNS

DNS(Domain Name System,域名系统),dns用于将域名解析解析为ip地址。

例如:给你www.baidu.com的主机名,你给 
我查出对应的ip地址:163.177.151.109。一些主机名还会有别名,如www.baidu.com就 
有别名www.a.shifen.com,甚至不止一个别名,或一个别名有2个ip地址。在linux机子 
上,运行nslookup(name service lookup)就是进行域名解析。如下面:

~$ nslookup www.baidu.com
Server:         127.0.0.1
Address:        127.0.0.1#53

Non-authoritative answer:
www.baidu.com   canonical name = www.a.shifen.com.
Name:   www.a.shifen.com
Address: 163.177.151.109
Name:   www.a.shifen.com
Address: 163.177.151.110

DNS工作方式分为递归查询和迭代查询,具体可参考下图

继续阅读Android DNS更新与DNS-Prefetch

ubuntu 18.04 Apache2启用HTTP/2

HTTP/2 可以让我们的应用更快、更简单、更稳定 – 这几词凑到一块是很罕见的!HTTP/2 将很多以前我们在应用中针对 HTTP/1.1 想出来的“歪招儿”一笔勾销,把解决那些问题的方案内置在了传输层中。不仅如此,它还为我们进一步优化应用和提升性能提供了全新的机会!

——《Web 性能权威指南》

Ubuntu18.04 官方源已经包含带有HTTP2模块的 Apache/2.4.29 ,所以我们可以很简单的启用 HTTP2。

$ sudo a2enmod http2

首先启用 http2 模块,然后在虚拟主机的配置文件中或者在Apache2的全局配置文件中加入:

Protocols h2 http/1.1

当客户端支持时优先使用 HTTP2 ,其次是 http/1.1,表明了一种优先顺序。目前为止就已经启用完成了,但如果你是使用的 Apache2+PHP 架构的应用程序,由于 mpm_prefork 模块不支持 mod_http2,所以我们需要切换 mpm_prefork、mod_php 到 mpm_event 和 php-fpm 来解决这个问题。

# Install php-fpm and enable
$ sudo apt install php-fpm

$ sudo systemctl enable php7.2-fpm

# To enable PHP 7.2 FPM in Apache2
$ sudo a2enmod proxy_fcgi setenvif

$ sudo a2enconf php7.2-fpm

# First to disable PHP 7.2/ mpm_prefork to avoid conflicts,then enable.
$ sudo a2dismod php7.2 mpm_prefork

$ sudo a2enmod mpm_event

继续阅读ubuntu 18.04 Apache2启用HTTP/2

解决GitHub的raw.githubusercontent.com无法连接问题

https://site.ip138.com/raw.Githubusercontent.com/

输入raw.githubusercontent.com

查询IP地址

修改hosts Ubuntu,CentOS及macOS直接在终端输入

$ sudo vi /etc/hosts

添加以下内容保存即可 (IP地址查询后相应修改,可以ping不同IP的延时 选择最佳IP地址

# GitHub Start
52.74.223.119 github.com
192.30.253.119 gist.github.com
54.169.195.247 api.github.com
185.199.111.153 assets-cdn.github.com
199.232.96.133 raw.githubusercontent.com
#151.101.76.133 raw.githubusercontent.com
151.101.108.133 user-images.githubusercontent.com
151.101.76.133 gist.githubusercontent.com
151.101.76.133 cloud.githubusercontent.com
151.101.76.133 camo.githubusercontent.com
151.101.76.133 avatars0.githubusercontent.com
151.101.76.133 avatars1.githubusercontent.com
151.101.76.133 avatars2.githubusercontent.com
151.101.76.133 avatars3.githubusercontent.com
151.101.76.133 avatars4.githubusercontent.com
151.101.76.133 avatars5.githubusercontent.com
151.101.76.133 avatars6.githubusercontent.com
151.101.76.133 avatars7.githubusercontent.com
151.101.76.133 avatars8.githubusercontent.com
# GitHub End

参考链接


ubuntu 20.04 & ubuntu18.04快速开启TCP BBR实现高效单边加速

`Linux Kernel` 内核升级到 `4.9` 及以上版本可以实现 `BBR` 加速,由于`Ubuntu 18.04` 默认的内核就是 `4.15`版本的内核,由于`Ubuntu 20.04` 默认的内核就是 `5.4` 版本的内核,并已经默认编译了 `TCP BBR` 模块,所以可以直接通过参数开启。

新的 `TCP` 拥塞控制算法 `BBR` (Bottleneck Bandwidth and RTT) 可以让服务器的带宽尽量跑慢,并且尽量不要有排队的情况,让网络服务更佳稳定和高效。

修改系统变量:

$ echo 'net.core.default_qdisc=fq' | sudo tee -a /etc/sysctl.conf 

$ echo 'net.ipv4.tcp_congestion_control=bbr' | sudo tee -a /etc/sysctl.conf

保存生效

$ sudo sysctl -p

执行

$ sysctl net.ipv4.tcp_available_congestion_control

如果结果是这样

$ sysctl net.ipv4.tcp_available_congestion_control 
net.ipv4.tcp_available_congestion_control = bbr cubic reno

就开启了。 执行 lsmod | grep bbr ,以检测 BBR 是否开启。

一般建议重启系统,重启后执行

$ sysctl net.ipv4.tcp_congestion_control 
net.ipv4.tcp_congestion_control = bbr

参考链接