삽질 1. timezone 부분

logstash, elasticsearch(plugis등), kibana 골치 아프니 UTC로 모두 바꾸니 편함...ㅡㅡ;


[logstash]

dd/MMM/yyyy:HH:mm:ss Z 했었는데 처리가 안되서.. 아래와 같이 했더니 해결...

         -> https://discuss.elastic.co/t/how-to-set-timestamp-timezone/28401/10

[kibana]

Settings -> Advanced -> dateFormat:tz -> UTC 선택




[logconf/apache.conf]

input {
  stdin { }
}

filter {
  grok {
    patterns_dir => ["./patterns"]
    # 본인 로그 패턴에 따라 설정
    match => { "message" => "%{COMMONAPACHELOG} %{NUMBER:responseTime} %{ALL_STR:qq1} %{ALL_STR:qq2} %{QS:referrer} %{QS:agent}" }
  }
  date {
    match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss +0900" ]
    timezone => "UTC"
  }
}

output {
  stdout { codec => json }
}


[logconf/apache.conf]

# 파일 단위 -> elasticsearch
input {
  file {
    path => "/usr/local/tomcat/logstash/dump_logs/ssl/*"
    start_position => "beginning"
  }
}

filter {
  grok {
    patterns_dir => ["./patterns"]
    # 본인 로그 패턴에 따라 설정
    match => { "message" => "%{COMMONAPACHELOG} %{ALL_STR:qq1} %{ALL_STR:qq2} %{QS:referrer} %{QS:agent}" }
  }
  date {
    match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss +0900" ]
    timezone => "UTC"
  }
}

output {
  elasticsearch { hosts => ["localhost:9200"]
                  index => "apache-access-log-%{+YYYY-MM-dd}"
                  document_type => "web01"
                }
  #stdout { codec => rubydebug }
}

[haproxy]

input {
  #stdin { }
  file {
    type => "searchWas"
    path => "/usr/local/tomcat/logstash/dump_logs/haproxy/haproxy-searchWas.log*"
    start_position => "beginning"
  }
  file {
    type => "aqmp"
    path => "/usr/local/tomcat/logstash/dump_logs/haproxy/haproxy-aqmp.log*"
    start_position => "beginning"
  }
}

  
filter {
  if [type] == "searchWas" {
    grok {
      patterns_dir => ["./patterns"]
    # 본인 로그 패턴에 따라 설정
      match => { "message" => "%{HAPROXYHTTP}" }
    }
    date {
      match => [ "accept_date", "dd/MMM/YYYY:HH:mm:ss.SSS" ]
      timezone => "UTC"
    }
  } else if [type] == "aqmp" {
    grok {
      patterns_dir => ["./patterns"]
      match => { "message" => "%{HAPROXYTCP}" }
    }
    date {
      match => [ "accept_date", "dd/MMM/YYYY:HH:mm:ss.SSS" ]
      timezone => "UTC"
    }
  }
}

output {
  #stdout { codec => json }
  
  if [type] == "searchWas" {
    elasticsearch {  
      hosts => ["localhost:9200"]
      index => "haproxy-access-log-%{+YYYY-MM-dd}"
      document_type => "searchWas"
    }
  } else if [type] == "aqmp" {
    elasticsearch {  
      hosts => ["localhost:9200"]
      index => "haproxy-access-log-%{+YYYY-MM-dd}"
      document_type => "aqmp"
    }
  }
}

[logconf/test-db.conf] db -> elasticsearch 케이스

input {
        jdbc {
                jdbc_driver_library => "/usr/local/tomcat/logstash/lib/mysql-connector-java-5.1.38.jar"
                jdbc_driver_class => "com.mysql.jdbc.Driver"
                jdbc_connection_string => "jdbc:mysql://mariadb-dev:3306/log"
                jdbc_user => "log"
                jdbc_password => "test"
                statement => "SELECT * FROM ez_apache_access_log_201602"
                #schedule => "* * * * *"
                jdbc_paging_enabled => "true"
                jdbc_page_size => "50000"

        }
}

[patterns/custom.conf]

ALL_STR .*

test exec

$ bin/logstash -f logconf/apache.conf 
192.168.1.100 - - [17/Jul/2016:21:08:51 +0900] "GET /test/list HTTP/1.1" 200 17194 5657 -/- (-%) "http://ddakker.test.com/test/add?test=1" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"

mappings -> 수동 index/document mapping 생성 예제

$ curl -XPUT http://localhost:9200/log_httpd -d '
{
  "mappings": {
    "web01": {
      "properties": {
        "req_query_string": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "req_dt": {
          "type": "string"
        },
        "referrer_query_string": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "referrer_domain": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "req_ext": {
          "type": "string"
        },
        "referrer_ext": {
          "type": "string"
        },
        "res_status": {
          "type": "string"
        },
        "req_mall_type": {
          "type": "string"
        },
        "@version": {
          "type": "string"
        },
        "ip": {
          "type": "string"
        },
        "req_uri": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "@timestamp": {
          "format": "strict_date_optional_time||epoch_millis",
          "type": "date"
        },
        "referrer_mall_type": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "method": {
          "type": "string"
        },
        "referrer_uri": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        }
      }
    }
  }
}'


외부 mysql 활용

yum install epel-release

yum groupinstall "Development Tools"

yum install openssl-devel readline-devel zlib-devel curl-devel libyaml-devel

yum install httpd httpd-devel

yum install ImageMagick ImageMagick-devel

## ubuntu desktop 에서 할때
# sudo apt-get install apache2 curl bison libbison-dev zlib1g-dev libssl-dev sqlite3 libsqlite3-dev autoconf automake build-essential libtool libreadline6-dev libyaml-dev libxml2-dev libcurl4-openssl-dev libssl-dev libgpg-error-dev autotools-dev imagemagick libmagickcore-dev libmagickwand-dev

wget http://www.ruby-lang.org/ko/downloads/

tar zxvf ruby-2.3.1.tar.gz 
cd ruby-2.3.1
./configure
make
make install

gem install bundler --no-rdoc --no-ri

wget http://www.redmine.org/releases/redmine-3.3.0.tar.gz

tar xvzf redmine-3.3.0.tar.gz

mv redmine-3.0.3 /usr/local/.
ln -s redmine-3.0.3 redmine


cp config/database.yml.example 

vi config/database.yml

bundle install --without development test postgresql sqlite

rake generate_secret_token
RAILS_ENV=production rake db:migrate
RAILS_ENV=production rake redmine:load_default_data

#ruby bin/rails server webrick –e production –b 192.168.1.11
bundle exec rails server webrick -e production
bundle exec rails server webrick -e production --port=40000
bundle exec rails server webrick -e production --binding=192.168.1.11 --port=40000


# thin 서버로 띄우기

gem install thin

vi Gemfile
# 하위 추가
gem "thin"

bundle install --path vendor/bundle

thin start -e production -p 40000 -c /usr/local/redmine --prefix=/redmine
curl http://192.168.1.11:40000/


# context path 바꿔보기

cp config/additional_environment.rb additional_environment.rb.example
vi config/additional_environment.rb
# 하위 추가
config.relative_url_root = '/redmine'


thin start -e production -p 40000 -c /usr/local/redmine --prefix=/redmine
thin start -d -e production -p 40000 -c /usr/local/redmine --prefix=/redmine
curl http://192.168.1.11:40000/redmine

# 기존 웹서버 httpd 에 추가하기

ProxyPass /redmine http://192.168.1.11:40000/redmine

curl http://dev.ddakker.pe.kr/redmine

# 시작/중지/관리
startup.sh
stop.sh
rake_plugin.sh
 
 
# 플러그인 설치
wget https://github.com/peclik/clipboard_image_paste/archive/master.zip
unzip master.zip
mv clipboard_image_paste-master plugins/clipboard_image_paste
 
RAILS_ENV=production rake redmine:plugins    (rake_plugin.sh 만들어 놓음)
 
# 설치된 플러그인
1. 이미지 클립보드 붙여 넣기 - Clipboard image paste
2. 일감 진행현황 그래프 - Progressive Projects List plugin
3. 일감 상황 그래프 - Redmine Graphs plugin
4. 로그인 히스토리 - Redmine Login Audit plugin
5. 일감 작업자별 현황 - Redmine (Monitoring & Controlling | Monitoramento & Controle)
 
 
# 플러그인 삭제
rake redmine:plugins:migrate NAME=플러그임이름 VERSION=0 RAILS_ENV=production
rm -Rf plugins/플러그인이름


Name

addtest

Context

Java type members (Automatically insert Checked)

Pattern

@${testType:newType(org.junit.Test)}
public void test_${name}() {
    ${staticImport:importStatic('org.junit.Assert.*', 'org.hamcrest.Matchers.*')}
}



Name

addlog

Context

Java type members (Automatically insert Checked)

Pattern

private static Logger log = LoggerFactory.getLogger(${enclosing_type}.class);
${imp:import(org.slf4j.Logger, org.slf4j.LoggerFactory)}



Name

addcon

Context

Java type members (Automatically insert Checked)

Pattern

@RequestMapping(value="${uri_name}", method={RequestMethod.GET})
public String ${method_name}(Model model) {
    return "${view_name}";
}
${imp:import(org.springframework.web.bind.annotation.RequestMapping, org.springframework.ui.Model, org.springframework.web.bind.annotation.RequestMethod)}



Name

addspringtest

Context

Java type members (Automatically insert Checked)

Pattern

${imp:import(org.junit.runner.RunWith, org.springframework.test.context.junit4.SpringJUnit4ClassRunner, org.springframework.test.context.ContextConfiguration)}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
        "classpath*:config/spring/context-common.xml",
        "classpath*:config/spring/context-transaction.xml",
        "classpath*:config/spring/context-datasource.xml"
})${cursor}

Gradle 에서 jar를 생성할때 의존된 jar들 포함시켜서 말고 싶을때가 있다.


https://github.com/musketyr/gradle-fatjar-plugin


buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'eu.appsatori:gradle-fatjar-plugin:0.3'
    }
}

apply plugin: 'eu.appsatori.fatjar'

Jolokia를 알게되서 최근까지 Servlet Container가 지원되는 부분에서만 이용했었는데 Servlet Container가 지원되지 않는 JVM 기반 Daemon의 MBean 을 모니터링 할 일이 생겨서 봤더니, Jolokia 에  JVM-Agent 있었군..



#!/bin/sh

..
..

PID=`ps -ef | grep java | grep "$DAEMON_NAME " | awk '{print $2}'`
echo " +$PID"

java -jar ...../jolokia-jvm-1.3.1-agent.jar start $PID --port=$MONITOR_PORT --host=$BIND_ADDR


# -- log
# +19102
# Started Jolokia for PID 19102
# http://---:---/jolokia/



Servlet Container 가 지원 될경우에는 WAR-Agent(jolokia-war-x.war) 를 Tomcat 이라면 webapps/ 하위에 복사 하거나 server.xml 에서 Context 부분에 추가 해주면 된다.


WebSocket 관련 개발을 하다가 데이터 송/수신 관련 데이터만 보고 싶다면..


Chrome 웹 스토어에서 "Dark WebSocket Terminal" 를 활용!!




프로세스와는 무관한 작업으로 인한 지연 현상이 발생하여 비동기 방식 처리를 고민하게되었다.


로그 히스토리를 DB에 기록하는 행위들인데 이 부분들에서 INSERT 시 지연이 발생하여 파일로 쌓았다가 긁어가야 하나.. 어떻게해야 하나 고민 하던 중 WAS 에서 제공하는 JMS 를 사용할까 하다가 ActiveMQ, RabbitMQ 를 셈플링 해보았다.


선택은 Cluster, Mirroring 설정이 간편한 RabbitMQ!!


[Cluster] https://www.rabbitmq.com/clustering.html

[Mirroring] https://www.rabbitmq.com/ha.html


그대로 따라 하기만 하면 잘 된다.


[설치]

esl-erlang_17.5-1~centos~6_amd64.rpm

rabbitmq-server-3.5.1-1.noarch.rpm


우선 서버당 /var/lib/rabbitmq/.erlang.cookie 값을 동일 하게 일치 시킨다.


하지만 난 하나의 물리 서버에 MQ서버 NODE 두개씩 올려보았다.


[rabbitmq@dev01]

   - mq11 - /usr/local/mq/domain/mq11

   - mq12 - /usr/local/mq/domain/mq12

[rabbitmq@dev02]

   - mq21 - /usr/local/mq/domain/mq21

   - mq22 - /usr/local/mq/domain/mq21



관리를 편리하게 하기 위해서 NODE 기반 명령어 스크립트를 만들어 둔다.

env.sh 에서 RabbitMQ 포트 번호 및 웹 관리 포트번호를 설정 하게 한다.


각각 디렉토리에 들어가서 각각 start.sh 를 실하면 알아서 뜬다.


env.sh - 기본 동적 설정

#!/bin/sh

NODE_PORT=각각 다르게 포트번호
NODE_MANAGEMENT_PORT=각각 다르게 포트번호(웹 관리 포트)
NODE_NAME=각각 NODE 이름


start.sh - MQ NODE 시작

#!/bin/sh

. ./env.sh


export RABBITMQ_NODE_PORT=$NODE_PORT 
export RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,$NODE_MANAGEMENT_PORT}]"
export RABBITMQ_NODENAME=$NODE_NAME
export RABBITMQ_MNESIA_DIR=/usr/local/mq/domains/$NODE_NAME/mnesia
export RABBITMQ_LOG_BASE=/usr/local/mq/domains/$NODE_NAME/logs
export RABBITMQ_CONFIG_FILE=/usr/local/mq/domains/$NODE_NAME/rabbitmq
/usr/sbin/rabbitmq-server -detached

echo "============================================================="
echo "   RabbitMQ Server 3.5.1-1.noarch           ddakker@gmail.com"
echo "-------------------------------------------------------------"
echo "RABBITMQ_NODENAME=$RABBITMQ_NODENAME"
echo "RABBITMQ_NODE_PORT=$RABBITMQ_NODE_PORT"
echo "NODE_MANAGEMENT_PORT=$NODE_MANAGEMENT_PORT"
echo "RABBITMQ_MNESIA_DIR=$RABBITMQ_MNESIA_DIR"
echo "RABBITMQ_LOG_BASE=$RABBITMQ_LOG_BASE"
echo "RABBITMQ_CONFIG_FILE=$RABBITMQ_CONFIG_FILE.config"
echo "============================================================="


stop.sh - MQ NODE 중지

#!/bin/sh

. ./env.sh

rabbitmqctl -n $NODE_NAME stop


app_start.sh - MQ NODE 관리앱 시작

#!/bin/sh

. ./env.sh

rabbitmqctl -n $NODE_NAME start_app


app_stop.sh - MQ NODE 관리앱 중지

#!/bin/sh

. ./env.sh

rabbitmqctl -n $NODE_NAME stop_app


ctl.sh - rabbitmqctl NODE 옵션 지정한 명령어

#!/bin/sh

. ./env.sh

echo "rabbitmqctl -n $NODE_NAME $1 $2 $3"
rabbitmqctl -n $NODE_NAME $1 $2 $3


status.sh - 상태 정보

#!/bin/sh

. ./env.sh

rabbitmqctl -n $NODE_NAME status
rabbitmqctl -n $NODE_NAME cluster_status


rabbitmq.config - 기본 설정 파일

[
   {mnesia, [{dump_log_write_threshold, 1000}]},
   {rabbit, [
        {log_levels, [{connection, info}]}
   ]},
   {rabbitmq_management, [
       {redirect_old_port, false}
   ]}
].


[NODE 별로 기동]

[rabbitmq@dev01 mq11]$ ./start.sh

[rabbitmq@dev01 mq12]$ ./start.sh

[rabbitmq@dev02 mq21]$ ./start.sh

[rabbitmq@dev02 mq22]$ ./start.sh


[Clustering] - mq11 을 기준으로 한다.(mq11 에서는 안 해도 됨)

[rabbitmq@dev01 mq12]$ ./app_stop.sh

[rabbitmq@dev01 mq12]$ ./ctl.sh join_cluster mq11@dev01

[rabbitmq@dev01 mq12]$ ./app_start.sh



[rabbitmq@dev02 mq21]$ ./app_stop.sh

[rabbitmq@dev02 mq21]$ ./ctl.sh join_cluster mq11@dev01

[rabbitmq@dev02 mq21]$./app_start.sh


[rabbitmq@dev02 mq22]$ ./app_stop.sh

[rabbitmq@dev02 mq22]$ ./ctl.sh join_cluster mq11@dev01

[rabbitmq@dev02 mq22]$ ./app_start.sh


[Mirroring] - Cluster 되면 아무곳에서 해도 됨

./ctl.sh set_policy 사용해도 되고, 그냥 "admin Tab" -> "Policies" 메뉴에서 UI상으로 하는게 편리!!

애래 Node 부분에 "+3" 부분이 보여야 함(정상/비정상 여부에 따라서 복제된 정보가 파랑숫자, 빨강숫자로 표현됨)

장애 후 복구된 서버에 이전데이터 동기(복제) 처리는 하지 않았음




[웹 접속 계정 생성 및 권한 부여] - Cluster 되면 아무곳에서 해도 됨

[rabbitmq@dev01 mq11]$ ./ctl.sh add_user test 1234

[rabbitmq@dev01 mq11]$ ./ctl.sh set_user_tags test administrator

그냥 "admin Tab" -> "Users" 메뉴에서 UI상으로 하는게 편리!!



앞단에 L4 를 붙이면 좋겠음








Slack 라는 업무용 메신저를 회사 동료가 알려줘서 우선 기존 모니터링 SMS 발송 부분을 Slack 으로 부분적으로 대체 해보기로 했다.


JAVA Client API로는 여러가지가 있고, 메시지 발송용으로는 아래 두가지 아무거나 사용하면 될 것 같다.

(https://api.slack.com/community)


SimpleSlackAPI - https://github.com/Ullink/simple-slack-api

SlackSDK - https://github.com/estebanwasinger/slack-sdk


SimpleSlackAPI 의 경우는 본인 계정 Token 기반으로만 글을 남길 수 있고, 내용 이외에 스타일 구조 메시지를 넣을 수 있다.(제목, 들여 쓰기 내용 등)

SlackSDK 의 경우는 본인 계정 Token 기반으로는 인증 하되 전송자명, 전송자 이미지를 수동으로 조정 가능하다.


각각 단순 셈플링시의 차이점이며 자세한 API는 아직 잘 모름!!

하지만 이정도만 해도 현재로서는 충분함!!


[SimpleSlackAPI]

package com.ullink.slack;


import org.junit.Test;

import com.ullink.slack.simpleslackapi.SlackAttachment;
import com.ullink.slack.simpleslackapi.SlackChannel;
import com.ullink.slack.simpleslackapi.SlackSession;
import com.ullink.slack.simpleslackapi.impl.SlackChannelImpl;
import com.ullink.slack.simpleslackapi.impl.SlackSessionFactory;

public class SlasckTest {
	@Test
	public void create() {
		final SlackSession session = SlackSessionFactory.createWebSocketSlackSession("개인 계정 Token 문자열");
		
		SlackChannel channel = new SlackChannelImpl("#cms-batch", null, null, null);
		session.sendMessage(channel, "내용이여", new SlackAttachment("title", "fallback", "text", "pretext"));
	}
}


[SlackSDK]

package msg.test;

import org.junit.Test;
import org.stevew.SlackClient;

public class SlackTest {
	@Test
	public void create1() {
		SlackClient sc = new SlackClient("개인 계정 Token 문자열");
		sc.sendMessage("내용이여", "#channel-name", "전송자명(쓰는대로 됨)", "http://../logo.png");
	}
}



Gradle

[build.gradle]

dependencies {
	compile 'com.yahoo.platform.yui:yuicompressor:2.4.8'
}

apply plugin: 'js'
apply plugin: 'css'
buildscript {
    repositories {
    	jcenter()
    }
    dependencies {
       classpath 'com.eriwen:gradle-js-plugin:1.12.1'
       classpath 'com.eriwen:gradle-css-plugin:1.11.1'
    }
}

javascript.source {
	def targetDir = "$project.projectDir" + File.separatorChar + "webapp" + File.separatorChar + "resources" + File.separatorChar + "js"
    dev {
        js {
            srcDir targetDir
            include "**/*.js"
            exclude "**/*.min.js"
        }
    }
}
css.source {
	def targetDir = "$project.projectDir" + File.separatorChar + "webapp" + File.separatorChar + "resources" + File.separatorChar + "css"
    dev {
        css {
            srcDir targetDir
            include "**/*.css"
            exclude "**/*.min.css"
        }
    }
}

javascript.source.dev.js.files.eachWithIndex { jsFile, i ->
	tasks.create(name: "minifyJs${i}", type: com.eriwen.gradle.js.tasks.MinifyJsTask) {
		source 	= jsFile
		dest 	= jsFile
		//dest = jsFile.getAbsolutePath().replace('.js', '.min.js')
	}
}
task allMinifyJs(dependsOn: tasks.matching { Task task ->
		if( "$targetServer" != "local" ){
			task.name.startsWith("minifyJs")
		} else {
			println '로컬에서는 minify 하지 않음'
		}
	}
)

css.source.dev.css.files.eachWithIndex { cssFile, i ->
	tasks.create(name: "minifyCss${i}", type: com.eriwen.gradle.css.tasks.MinifyCssTask) {
		source 	= cssFile
		dest 	= cssFile
    	//dest = cssFile.getAbsolutePath().replace('.css','.min.css')
    	yuicompressor {
    		lineBreakPos = -1
    	}
    }
}
task allMinifyCss(dependsOn: tasks.matching { Task task ->
		if ( "$targetServer" != "local" ){
			task.name.startsWith("minifyCss")
		} else {
			println '로컬에서는 minify 하지 않음'
		}
	}
)



Ant

https://github.com/yui/yuicompressor

[build.xml]

	<path id="yui.classpath">
		<fileset dir="./lib">
			<include name="ant-yui-compressor-taskdef-1.0.jar" />
			<include name="yuicompressor-2.4.8.jar" />
		</fileset>
	</path>

	<taskdef resource="yuicompressor.tasks" classpathref="yui.classpath" />

	<target name="compress" description="Compress JS files using YUI Compressor">
		<!-- Compress JS files using YUI Compressor -->
		<ant-yui-compressor todir="./webapp/resources/js" deleteOriginal="false">
			<fileset dir="./webapp/resources/js">
				<include name="**/*.js" />
				<include name="**/*.min.js" />
				<exclude name="ez-common.js" />
				<exclude name="IBSheetPro3/IBSheetInfo_UTF8.js" />
			</fileset>
			<mapper type="glob" from="*.js" to="*.js" />
		</ant-yui-compressor>

		<!-- Compress CSS files using YUI Compressor -->
		<ant-yui-compressor todir="./webapp/resources/css" deleteOriginal="false">
			<fileset dir="./webapp/resources/css">
				<include name="**/*.css" />
				<include name="**/*.min.css" />
			</fileset>
			<mapper type="glob" from="*.css" to="*.css" />
		</ant-yui-compressor>
	</target>


2012-10-13 stable release 이후 버전에서 부터 디자인이 전체적으로 변경되면서 가로사이즈가 75em<--으로 고정되어졌음


변경 하려면 ../lib/tpl/dokuwiki/style.ini

__site_width__      = "75em" 부분을 __site_width__      = "100%" 와 같이 변경한다.




두번째로 IE9에서(다른 IE버전은 모르겠음..) 편집 버튼 폰트가 너무 작아 이상하게 보이는 문제는


../lib/tpl/dokuwiki/css/_edit.css 파일에서 .dokuwiki .secedit input.button 부분에서 font-size: 75%; 부분을 font-size: 11px; 와 같이 변경한다.



세번째로 font-size 가 우리 정서적으로 맞지않아.. 12px로 변경.. 


/lib/tpl/dokuwiki/css/basic.less 의 body 부분에서 font: normal 12px Arial, sans-serif; 와 같이 변경


네번째로 li의 간격 조절, 같은 파일의 li,dd 부분의 margin: 0 0 0 1.5em; 를 margin: 6px 0 0 1.5em; 와 같이 변경


그 외.. 이것..저것..



이 후 touch ../conf/local.php 해주면 적용된다.






2012-10-13 stable release 이전 버전도 style 수정이 필요 하다면 /lib/tpl/default/ 하위 css를 수정 후 local.php 파일을 touch 해주면 적용된다.


이전 디자인이 더 맘에 드는 이유는....

+ Recent posts