精华内容
下载资源
问答
  • Time类型 在Flink中常用的Time类型: 处理时间 摄取时间 事件时间 处理时间 ...是上图中,最后一步的处理时间,表示服务器中...例如:个小时的处理时间窗口,将会包含个小时内的到达服务器内的所有数据。例如...

    Time类型

    在Flink中常用的Time类型:

    • 处理时间
    • 摄取时间
    • 事件时间

    处理时间

    是上图中,最后一步的处理时间,表示服务器中执行相关操作的处理时间。例如一些算子操作时间,在服务器上面的时间。

    如果你以处理时间作为流处理的时间处理方式,那么所有的基于时间的操作都会使用服务器的时间,来运行相关的操作。例如:一个小时的处理时间窗口,将会包含一个小时内的到达服务器内的所有数据。例如应用程序9:15am开始执行,第一个小时的时间处理窗口会包含所有的9:15到10:15内的事件数据,下一个时间窗口是10:15到11:15内的所有数据。

    处理时间是最简单的事件处理方式,并不需要流和机器的时间协调。因此提供了高性能和低延迟。然而在分布式环境中或者异步环境中处理时间并不能够提供准确性(也就是说在处理数据时,由于网络的抖动在一个处理时间窗口中例如9:15到10:15,很大可能包括9:00的事件数据)。

    事件时间

    事件时间是每一个设备上每一个单独事件发生的时间例如手机登录APP的日志时间。这个时间就是这条数据记录的时间。每一条数据都有一个时间戳表示这条数据的事件发生时间。这个时间取决于每条数据,而并不会依赖于机器的时间。事件时间处理时必须指定如何获得Event Time watermarks(用来描述Event Time如何处理)。

    按照事件时间处理数据,处理结果应该是完全一致,也就是说无论处理多少次结果都是一样的,这就是所谓的大数据处理的幂等性。 不管事件到达时间和事件是不是有序到达(在生产环境中,数据往往进入到服务器中的时间和顺序是不一定的,有可能先产生的数据后到达服务器,这取决于很多网络因素)

    摄取时间

    摄取时间表示某个事件数据进入到Flink的时间。在source操作中,每条记录都会得到source的当前时间戳,也就是接收到的数据自动会有一个摄取时间,也就是例如时间窗都是基于这个时间来处理的。

    摄取时间是处于事件时间和处理时间之间。如上图所示。摄取时间是有成本的,但是却是结果可预测的。因为摄取时间使用了稳定的时间戳(在source端只会分配一次),每一条数据的时间戳都是固定的。并且同一摄取时间的数据有可能被分配到不同的处理时间窗口中。

    Windows

    Windows使我们处理无限数据流(源源不断的进来)的核心部件。Windows把我们的数据流拆成一个个的buckets。我们需要把算子作用到buckets上面去。

    第一件事情就是需要指定我们的流数据是不是有key,有key和没有key对应的算子是完全不一样的。

    Keyed windows

    带keyby,会结合windows一起使用。输入的数据内容中的任意属性都可以作为一个key。在这个流上可以允许窗口多任务并行计算,每一个逻辑key都可以被独立计算,相同的key的数据会被发送到相同的并行任务中去处理。

    Non-Keyed windows

    通过使用windowAll来指定。原始的数据流不会被拆分成多个逻辑任务,所有窗口逻辑都是一个窗口任务来执行,所以并行度是1。

    windows 生命周期

    简而言之,当第一个元素到达对应的窗口时,一个windows就会被开始创建。当时间(不管是event时间还是processing时间)达到时间戳范围,就会移除窗口。另外,每一个窗口都有一个Trigger和window Functions,当数据到达窗口后,执行的函数就是window Functions,这个函数包含了对这个窗口内容的所有计算,当Trigger达到一定条件之后,就会触发。

    Windows Assigners

    在指定流数据是否带key之后,下一步就是定义窗口的分配器(windows assigner),windows assigner的职责是定义每一个传入的元素如何分配到窗口内。对于keyby使用window()方法,对于non-keyby使用windowAll()方法。

    WindowAssigner is responsible for assigning each incoming element to one or more windows. 

     每个传入的数据分配给一个或多个窗口。

    Flink内置的window assigner对于大多数场景来讲基本上是够用的(tumbling windows滚动窗口, sliding windows滑动窗口, session windows会话窗口 and global windows全局窗口)。也可以通过继承WindowAssigner来自定义一个window assigner。所有的内置window assigner(除了全局窗口)都是基于时间(处理时间或事件时间)来分配数据的。

    基于时间的窗口有一个开始的timestamp(inclusive)和结束timestamp(exclusive)表示窗口的大小。

    Flink中对于窗口的划分有两大类,第一大类是基于time(用的最多),第二大类是基于count。

    Tumbling Windows 滚动窗口

    滚动窗口分配器将分配每一个元素到一个指定大小的窗口,这种类型的窗口有一个固定的大小而且不会有重叠的。上面这张图就是随着时间流按照指定的时间间隔拆开。

    简单实例代码:

    Scala

    object WindosApp {
      def main(args: Array[String]): Unit = {
        val env = StreamExecutionEnvironment.getExecutionEnvironment
        val text = env.socketTextStream("192.168.227.128", 9999)
        text.flatMap(_.split(",")).map((_,1)).keyBy(0).timeWindow(Time.seconds(5)).sum(1).print().setParallelism(1)
    
        env.execute("WindosApp")
      }
    
    }

    上面的代码表示监听socket数据流,每隔5秒获取一次数据。timeWindow表示根据时间来划分窗口,(此外还有countWindow根据数量来划分窗口)。默认时间是processTime处理时间。

    Java

    public class JavaWindowApp {
        public static void main(String[] args) throws Exception {
            StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
            DataStreamSource<String> text = env.socketTextStream("192.168.227.128", 9999);
            text.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
                @Override
                public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
                    String[] tokens = value.toLowerCase().split(",");
                    for(String token: tokens) {
                        if(token.length()>0){
                            out.collect(new Tuple2<String, Integer>(token, 1));
                        }
                    }
                }
            }).keyBy(0).timeWindow(Time.seconds(5)).sum(1).print().setParallelism(1);
    
            env.execute("JavaWindowApp");
    
        }
    }

    Sliding Windows滑动窗口

    滑动窗口分配器分配每一个元素到一个固定大小的窗口,类似于滚动窗口,窗口大小可以通过配置进行修改,但是滑动窗口还有另外一个附加滑动参数控制滑动窗口什么时候启动,所以这个窗口是有可能重叠的。

    上面图的意思是window1的窗口大小是10分钟,滑动大小是5分钟,也就是每隔5分钟产生一个窗口,这个窗口的大小是10分钟,这个窗口就是window2,然后window2又过5分钟产生一个窗口,窗口的大小是10分钟 window3,以此类推。所以滑动窗口处理的数据可能会有重叠。一个数据元素可能会在多个窗口中进行处理。

    使用场景:每个半个小时统计前一个小时的TopN。

    object WindosApp {
      def main(args: Array[String]): Unit = {
        val env = StreamExecutionEnvironment.getExecutionEnvironment
        val text = env.socketTextStream("192.168.227.128", 9999)
        text.flatMap(_.split(",")).map((_,1)).keyBy(0)
          //.timeWindow(Time.seconds(5)) # 滚动窗口
          .timeWindow(Time.seconds(10),Time.seconds(5))
          .sum(1).print().setParallelism(1)
    
        env.execute("WindosApp")
      }
    
    }

    每隔5秒统计近10秒的数据。所以当服务器端输入:

    a,a,a,b,b,b
    a,a,a,b,b,b
    a,b,a,b,a,a
    

    时,控制台会打印两遍结果:

    (a,10)
    (b,8)
    (b,8)
    (a,10)

    Window Functions

    在定义窗口分配器之后,就需要指定基于每一个窗口的计算方法了(在上面的例子中我们做了一个keyby sum操作)。window function会处理窗口中的每一个元素。window function包括如下几个:

    • ReduceFunction
    • AggregationFunction
    • FoldFunction
    • ProcessWindowFunction

    ReduceFunction和AggregationFunction的执行效率更高,因为Flink会在数据到达每一个窗口时首先做一个增量聚合操作。ProcessWindowFunction拿到的是包含在窗口中的所有的元素以及附加信息一个Iterable,是一个全量聚合。因此ProcessWindowFunction的执行效率不高,因为Flink会缓存窗口中的所有数据。

    ReduceFunction

    input中的两个元素进行结合产生一个同样类型的输出。这里我们举例,通过传入的数据类型是数值类型来演示增量效果。

    Scala

    object WindowReduceApp {
      def main(args: Array[String]): Unit = {
        val env = StreamExecutionEnvironment.getExecutionEnvironment
        val text = env.socketTextStream("192.168.227.128", 9999)
        text.flatMap(_.split(","))
          .map(x=>(1,x.toInt)) // 1,2,3,4,5 => (1,1) (1,2) (1,3) (1,4) (1,5)
          .keyBy(0) //因为key都是1, 所以所有的元素都到一个task去执行
          .timeWindow(Time.seconds(5)) // 滚动窗口
          .reduce((v1, v2) => {  reduce函数作用在窗口之上,就可以完成窗口中的增量操作,不用等所有的数据到达之后进行一次性处理,而是数据两两处理
          println(v1 + "....." + v2)
          (v1._1, v1._2 + v2._2)
        })
          .print().setParallelism(1)
        env.execute("WindowReduceApp")
      }
    }

    服务器端输入:

    1,2,3,4,5
    

    控制台中输出如下:

    (1,1).....(1,2)
    (1,3).....(1,3)
    (1,6).....(1,4)
    (1,10).....(1,5)
    (1,15)

    reduce函数作用在窗口之上,就可以完成窗口中的增量操作,不用等所有的数据到达之后进行一次性处理,而是数据两两处理。

    Java

    public class JavaWindowReduceApp {
        public static void main(String[] args) throws Exception {
            StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
            DataStreamSource<String> text = env.socketTextStream("192.168.227.128", 9999);
            text.flatMap(new FlatMapFunction<String, Tuple2<Integer, Integer>>() {
                @Override
                public void flatMap(String value, Collector<Tuple2<Integer, Integer>> out) throws Exception {
                    String[] tokens = value.toLowerCase().split(",");
                    for(String token: tokens) {
                        if(token.length()>0){
                            out.collect(new Tuple2<Integer, Integer>(1, Integer.parseInt(token)));
                        }
                    }
                }
            }).keyBy(0).timeWindow(Time.seconds(5))
                    .reduce(new ReduceFunction<Tuple2<Integer, Integer>>() {
                        @Override
                        public Tuple2<Integer, Integer> reduce(Tuple2<Integer, Integer> value1, Tuple2<Integer, Integer> value2) throws Exception {
                            System.out.println("value1 = [" + value1 + "], value2 = [" + value2 + "]");
                            return new Tuple2<>(value1.f0,value1.f1 + value2.f1);
                        }
                    })
                    .print().setParallelism(1);
    
            env.execute("JavaWindowApp");
    
        }
    }

    输出结果如下:

    value1 = [(1,1)], value2 = [(1,2)]
    value1 = [(1,3)], value2 = [(1,3)]
    value1 = [(1,6)], value2 = [(1,4)]
    value1 = [(1,10)], value2 = [(1,5)]
    (1,15)

    ProcessWindowFunction

    ProcessWindowFunction可以拿到一个Iterable,可以拿到窗口中的所有元素,并且有一个上下文对象可以访问时间和状态信息,比reducefunction可以提供更多的功能。但这样却可以带来资源和性能的开销,因为元素并不能通过增量的方式去聚合,相反,它需要把所有的数据都放在一个buffer中。

    public class JavaWindowProcessApp {
        public static void main(String[] args) throws Exception {
            StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
            DataStreamSource<String> text = env.socketTextStream("192.168.227.128", 9999);
            text.flatMap(new FlatMapFunction<String, Tuple2<Integer, Integer>>() {
                @Override
                public void flatMap(String value, Collector<Tuple2<Integer, Integer>> out) throws Exception {
                    String[] tokens = value.toLowerCase().split(",");
                    for(String token: tokens) {
                        if(token.length()>0){
                            out.collect(new Tuple2<Integer, Integer>(1, Integer.parseInt(token)));
                        }
                    }
                }
            }).keyBy(0).timeWindow(Time.seconds(5))
                    .process(new ProcessWindowFunction<Tuple2<Integer, Integer>, Object, Tuple, TimeWindow>() {
                        @Override
                        public void process(Tuple tuple, Context context, Iterable<Tuple2<Integer, Integer>> elements, Collector<Object> out) throws Exception {
                            System.out.println("tuple = [" + tuple + "], context = [" + context + "], elements = [" + elements + "], out = [" + out + "]");
                            long count = 0;
                            for(Tuple2<Integer, Integer> in:elements) {
                                count++;
                            }
                            out.collect("window:" + context.window() + "count:" + count);
                        }
                    })
                    .print().setParallelism(1);
    
            env.execute("JavaWindowApp");
    
        }
    }

    服务器输入:

    1,2,3,4,5

    控制台输出:

    tuple = [(1)], context = [org.apache.flink.streaming.runtime.operators.windowing.functions.InternalProcessWindowContext@40e09d6c], elements = [[(1,1), (1,2), (1,3), (1,4), (1,5)]], out = [org.apache.flink.streaming.api.operators.TimestampedCollector@4e277b00]
    window:TimeWindow{start=1568542160000, end=1568542165000}count:5

    只输出一次,说明是等待所有数据都拿到之后才进行处理。

    使用场景:窗口内的数据进行排序。在Reduce中是无法进行排序的。

    展开全文
  • 1、脚本包说明脚本包并不是独立的软件包类型,通常安装的是源码包;脚本包是人为把安装过程变成了自动安装的脚本。只要执行脚本,定义简单的参数,就可以完成...2、Webmin2.1、Webmin简介Webmin是个基于Web的Linux...

    1、脚本包说明

    脚本包并不是独立的软件包类型,通常安装的是源码包;

    脚本包是人为把安装过程变成了自动安装的脚本。只要执行脚本,定义简单的参数,就可以完成软件包的安装;

    脚本包类似于Windows环境下软件安装的方式。只不过Windows是图形界面,需要点击下一步下一步等操作,而Linux是图形界面,需要按要求输入内容后回车;

    2、Webmin

    2.1、Webmin简介

    Webmin是一个基于Web的Linux系统管理界面。如果系统中安装了Webmin,就可以通过图形化界面的方式来操作管理Linux服务器。

    2.2、Webmin安装

    下面我们以安装Webmin来演示一下脚本包的安装过程。

    2.2.1、下载Webmin软件

    2d3eaf68b794

    点击进入,然后选择webmin-1.962.tar.gz文件下载

    2d3eaf68b794

    2.2.2、上传文件到Linux服务器

    将下载后的文件上传到 /usr/local/src 目录下面,如下图所示:

    2d3eaf68b794

    2.2.3、解压缩文件

    进入/usr/local/src目录,执行命令:

    cd /usr/local/src

    解压缩文件webmin-1.962.tar.gz,执行命令:

    tar -zxvf webmin-1.962.tar.gz

    2.2.4、执行安装脚本

    进入解压缩后的文件目录,执行命令

    cd webmin-1.962/

    查看目录下面的文件

    2d3eaf68b794

    红框中标注的是setup.sh文件,这个是安装文件。通常Windows环境下面安装文件是Setup.exe。

    执行命令进入安装模式

    ./setup.sh

    注意:要使用命令./setup.sh,如果直接使用setup.sh命令会报错。

    2d3eaf68b794

    我们使用回车表示下一步。在安装过程中,会要求输入配置文件目录、日志文件目录、端口号、用户名密码等。我们可以都使用默认,也可以自己输入。

    2d3eaf68b794

    我这里使用的都是默认值,端口号是10000,用户名:admin 密码为空。

    2.2.5、登录Webmin

    在浏览器中输入地址 http://IP:10000 如下图所示:

    2d3eaf68b794

    输入用户名密码,进入系统。

    进入系统后是英文界面,在查找中输入language可以将界面更改为中文,如下图所示:

    2d3eaf68b794

    在此界面中也可以进行Linux服务器的管理。

    此处安装Webmin只是用于演示如何使用脚本包安装。并不推荐大家使用Webmin进行服务器管理,还是需要掌握命令!!!

    展开全文
  • 个运行JavaWeb项目,我们需要知道这个系统运行的状况,这里我选择用sigar来获取本地系统信息。Sigar是Hyperic-hq产品的基础包,是Hyperic HQ主要的数据收集组件。它用来从许多平台收集系统和处理信息. 这些平台包括...

    一个运行JavaWeb项目,我们需要知道这个系统运行的状况,这里我选择用sigar来获取本地系统信息。

    Sigar是Hyperic-hq产品的基础包,是Hyperic HQ主要的数据收集组件。它用来从许多平台收集系统和处理信息. 这些平台包括:Linux, Windows, Solaris, AIX, HP-UX, FreeBSD and Mac。 OSX.Sigar有C,C#,Java和Perl API,java版的API为sigar.jar。sigar.jar的底层是用C语言编写的,它通过本地方法来调用操作系统API来获取系统相关数据。

    1、通过Gradle依赖jar包

    compile group: 'org.fusesource', name: 'sigar', version: '1.6.4'
    

    2、添加相应的系统配置文件如win下的sigar-x86-winnt.dll,Linux下的libsigar-x86-linux.so及mac os下的libsigar-universal64-macosx.dylib等文件

    在ManagerController添加初始化配置文件代码

    //静态代码块
    static {
        try {
            initSigar();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //初始化sigar的配置文件
    private static void initSigar() throws IOException {
        SigarLoader loader = new SigarLoader(Sigar.class);
        String lib = null;
    
        try {
            lib = loader.getLibraryName();
        } catch (ArchNotSupportedException var7) {
            logger.error(var7.getMessage(), var7);
        }
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        Resource resource = resourceLoader.getResource("classpath:/sigar/" + lib);
        if (resource.exists()) {
            InputStream is = resource.getInputStream();
            File tempDir = FileUtil.createTempDirectory();
            BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(new File(tempDir, lib), false));
            StreamUtil.copy(is, os);
            is.close();
            os.close();
            System.setProperty("org.hyperic.sigar.path", tempDir.getCanonicalPath());
        }
    }
    

    3、使用sigar获取系统使用情况

    /**
     * 管理台首页
     */
    @RequestMapping("/index")
    public String index(HttpServletRequest request, Model model) throws IOException {
        String user = (String) request.getAttribute("user");
        model.addAttribute("user", user);
        Sigar sigar;
        try {
            //当前时间
            model.addAttribute("nowTime", DateUtil.getDateTime());
            //应用服务器
            ServletContext servletContext = request.getSession().getServletContext();
            model.addAttribute("servletServer", servletContext.getServerInfo());
            //JDK版本
            model.addAttribute("javaVersion", SystemUtil.getJavaVersion());
            sigar = new Sigar();
            CpuInfo[] cpuInfoList = sigar.getCpuInfoList();
            //CPU信息
            model.addAttribute("cpu", cpuInfoList[0].getVendor() + "(" + cpuInfoList[0].getModel() + ") " + cpuInfoList[0].getMhz() + "MHz x " + cpuInfoList.length + "核");
            //操作系统
            String osname = System.getProperties().getProperty("os.name");
            model.addAttribute("osname", osname);
            //服务器内存
            Mem freeMemory = sigar.getMem();
            model.addAttribute("mem", String.format("%.2fG", new Object[]{Double.valueOf((double) freeMemory.getTotal() / 1.073741824E9D)}));
            //JVM内存
            model.addAttribute("jvmMaxMem", String.format("%.2fM", new Object[]{Float.valueOf((float) Runtime.getRuntime().maxMemory() / 1048576.0F)}));
            //
            model.addAttribute("memUsedPercent", String.format("%.2f", new Object[]{Double.valueOf(freeMemory.getUsedPercent())}));
            //CPU使用
            model.addAttribute("cpuUsed", String.format("%.2f", new Object[]{Double.valueOf(CpuPerc.format(sigar.getCpuPerc().getCombined()).replace("%", ""))}));
            long pid = sigar.getPid();
            long startTime = sigar.getProcTime(pid).getStartTime();
            //系统运行时间
            model.addAttribute("runningTime", DateUtil.friendDuration(System.currentTimeMillis() - startTime));
            //系统内存使用
            long maxMemory2 = Runtime.getRuntime().maxMemory();
            long freeMemory1 = Runtime.getRuntime().freeMemory();
            //JVM内存使用
            model.addAttribute("useableMemeory", String.format("%.2f", new Object[]{Double.valueOf((double) (maxMemory2 - freeMemory1) / ((double) maxMemory2 * 1.0D) * 100.0D)}));
        } catch (SigarException e) {
            logger.error("使用sigar获取服务器信息错误:", e);
        }
        return "manager/index";
    }
    
    //时间工具类计算总时间
    public static String friendDuration(long ms) {
        short ss = 1000;
        int mi = ss * 60;
        int hh = mi * 60;
        int dd = hh * 24;
        long day = ms / (long) dd;
        long hour = (ms - day * (long) dd) / (long) hh;
        long minute = (ms - day * (long) dd - hour * (long) hh) / (long) mi;
        long second = (ms - day * (long) dd - hour * (long) hh - minute * (long) mi) / (long) ss;
        long milliSecond = ms - day * (long) dd - hour * (long) hh - minute * (long) mi - second * (long) ss;
        StringBuilder str = new StringBuilder();
        if (day > 0L) {
            str.append(day).append("天,");
        }
        if (hour > 0L) {
            str.append(hour).append("小时,");
        }
        if (minute > 0L) {
            str.append(minute).append("分钟,");
        }
        if (second > 0L) {
            str.append(second).append("秒,");
        }
        if (milliSecond > 0L) {
            str.append(milliSecond).append("毫秒,");
        }
        if (str.length() > 0) {
            str = str.deleteCharAt(str.length() - 1);
        }
        return str.toString();
    }
    

    4、页面展示

    <tr>
      <td>管理员个数:</td>
      <td>1 人</td>
      <td>当前时间:</td>
      <td id="nowTime">${nowTime}</td>
    </tr>
    <tr>
      <td>CPU:</td>
      <td>${cpu}</td>
      <td>JDK版本:</td>
      <td>${javaVersion}</td>
    </tr>
    <tr>
      <td>操作系统:</td>
      <td>${osname}</td>
      <td>系统运行时间:</td>
      <td>${runningTime}</td>
    </tr>
    <tr>
      <td>服务器内存:</td>
      <td>${mem}</td>
      <td>JVM内存:</td>
      <td>${jvmMaxMem}</td>
    </tr>
    <tr>
      <td>系统内存使用:</td>
      <td>${memUsedPercent}%</td>
      <td>JVM内存使用:</td>
      <td>${useableMemeory}%</td>
    </tr>
    <tr>
      <td>系统CPU使用:</td>
      <td>${cpuUsed}%</td>
      <td>应用服务器:</td>
      <td>${servletServer}</td>
    </tr>
    

    页面情况如下,系统具体使用情况就能看的一目了然。如需其他的数据,可以自行去查看API使用。​


    欢迎转载,转载请注明出处 http://www.dingyinwu.com/article/62.html 

    如果文章中有任何问题或者可以改进的地方,请大家多提提意见,我会非常感激。




    展开全文
  • Unity3D研究院之IOS在Windows上查看日志就像Android的adb一样方便(零一) https://www.xuanyusong.com/archives/4541 我以前写过篇 Unity3D研究院专治IOS查看日志各种不服(九十五) 但是今天无意间发现了...

    Unity3D研究院之IOS在Windows上查看日志就像Android的adb一样方便(一百零一)

    https://www.xuanyusong.com/archives/4541

    我以前写过一篇 Unity3D研究院专治IOS查看日志各种不服(九十五) 但是今天无意间发现了一个工具iOSLogInfo,这个工具比之前的做法更好更方便。

    下载地址:https://www.blackberry.com/blackberrytraining/web/KB_Resources/KB36986_iOSLogInfo_4.3.4.zip

    Unity中的日志一般分为两种,一种是Debug.Log这种我们主动打的日志,还有一种就是一些代码错误引起的异常了。

     

    iOSLogInfo下载好以后,就可以使用指令了。

    sdsiosloginfo.exe -d > xcode.log

    似乎用起来不然方便,所以我们写一个批处理放在iOSLogInfo解压后的文件夹中。

     

    run.bat

    1

    2

    3

    4

    5

    6

    7

    @echo off  

    set sdsiosloginfo="%~dp0\sdsiosloginfo.exe"

    set xcodelog="%~dp0\xcode.log"

    echo "关闭窗口停止"

    %sdsiosloginfo% -d >%xcodelog%

     

    pause

    Windows查看日志的方式

    1.手机连上usb 确保连接正常, 可以安装itools一类的工具。

    2.双击run.bat

    3.关闭控制台,打开iOSLogInfo目录下生成的xcode.log文件

    4.最后看看xcode.log的日志,如下图所示,我们自己打的日志,又或者异常日志都被正常的输出了。

     

    这样就可以让IOS在Windows上查看日志就像Android一样方便啦。

     

    最近有朋友问我能否在mac上也可以这样方便的查看日志,首先下载 Apple Configurator 2 
    在Unity里写点日志。

    1

    2

    3

    4

    5

    6

    7

    8

    9

        private void Update()

        {

            Debug.Log("yusongmomo!");

            Debug.LogError("yusongmomo error!");

            Debug.LogWarning("yusongmomo warn!");

     

            int[] a = new int[1];

            a[2] = 100; //异常

        }

    打开软件后选择自己的设备-》控制台。然后就可以看日志了

     

     

     

     

     

    展开全文
  • 我以前写过篇 Unity3D研究院专治IOS 查看日志各种不服(九十五) 但是今天无意间发现了个工具iOSLogInfo,这个 工具 比之前的做法更好更方便。Unity中的日志一般分为两种,种是Debug.Log这种我们主动打的日志,...
  • 之再续:教你一步一步用c语言实现sift算法、下

    万次阅读 热门讨论 2011-03-13 13:10:00
    教你一步一步用c语言实现sift算法、下作者:July、二零一一年三月二日出处:http://blog.csdn.net/v_JULY_v。参考:Rob Hess维护的sift 库环境:windows xp+vc6.0条件:c语言实现。说明:本BLOG内会陆续一一实现...
  • 之再续:教你一步一步用c语言实现sift算法、上

    万次阅读 多人点赞 2011-03-13 09:32:00
    教你一步一步用c语言实现sift算法、上作者:July、二零一一年三月二日出处:http://blog.csdn.net/v_JULY_v参考:Rob Hess维护的sift 库环境:windows xp+vc6.0条件:c语言实现。说明:本BLOG内会陆续一一实现所有...
  •  教你一步一步用c语言实现sift算法、上 ...作者:July、二零一一年三月二日 出处:http://blog.csdn.net/v_JULY_v 参考:Rob Hess维护的sift 库 环境:windows xp+vc6.0 条件:c语言实现。 说明:本BL
  • 十一章 配置管理 88 1.什么是配置管理 88 2.配置管理流程 88 3.SVN实战 88 配置管理工具SVN操作过程手册 90 一、 如何创建“project”项目版本库 90 二、 如何查看创建的“project”项目版本库 95 三、 在版本...
  • 工作中接触linux时间也不算短了,不同于Windows的图形化操作,使用linux几乎百分之九十五的情况是在命令行下过日子,过去的两年里,零零碎碎整理过版自己工作中涉及到和学习过的命令(不过常用的只有三个左右),...
  • 九十一期 Apache ECharts (incubating) 的微信小程序版本 从 RxJS 到 Flink:如何处理数据流? 从0到1开发可视化数据大屏(上) 使用 mask 实现视频弹幕人物遮罩过滤 Create interactive videos in React ...

空空如也

空空如也

1 2 3
收藏数 46
精华内容 18
关键字:

windows十一九零九