캠핑과 개발

네이버 지도 API를 사용하여 개발한 사이트가 있는데 해당 사이트는 https로 되어 있습니다.

하지만 지도를 보여주는 메뉴를 선택하게 되면 지도는 표시 되지 않으며 크롬 주소창 끝쪽에 방패모양의 아이콘만 표시되며 지도는 표시가 되지 않습니다.

해당 증상 및 해결방법은 아래와 같습니다.


크롬에서는 https로 연결시 http 컨텐츠를 차단한다고 합니다.

이 옵션을 해제할 수 있는 기능은 별도로 제공되어 있지 않으며, 크롬 구동시 다음 옵션을 주면 http 연결된 컨텐츠도 다운로드 합니다.


-allow-running-insecure-content





증상 

'이 페이지가 인증되지 않은 소스에서 스크립트를 로드하려고 시도하고 있습니다.'라는 오류가 표시되는 이유는 Chrome에서 안전하지 않은 사이트로부터 사용자를 보호하고 페이지에 표시된 사용자 정보가 악용되지 않도록 하기 위해서입니다. 이 경우 검색주소창에 방패  가 표시됩니다.


알림 무시

권장되지는 않지만 원하는 경우 안전하지 않은 스크립트 로드를 클릭하여 페이지의 알림을 무시할 수 있습니다. 그럼 Chrome이 페이지를 새로고침하여 안전하지 않은 콘텐츠를 포함한 모든 콘텐츠를 로드하게 됩니다. 해당 페이지가 안전하지 않다고 표시하기 위해 상단의 검색주소창의 https에 빨간색 줄 이 표시됩니다.

특정 웹 콘텐츠 차단

설정 페이지에서 자바스크립트나 이미지 등 특정 유형의 웹 콘텐츠가 모든 사이트에 표시되지 않도록 선택할 수 있습니다. 자세한 내용은 웹 콘텐츠 설정 조정을 참조하세요.

사이트의 문제 스크립트 찾기

웹 개발자인 경우 사이트에서 발견된 안전하지 않은 스크립트를 확인할 수 있습니다. 상단 툴바에서 보기 > 개발자 > 자바스크립트 콘솔을 클릭하세요. 안전하지 않은 코드나 유해한 확장 프로그램이 문제의 원인일 수 있습니다.


참고 : https://support.google.com/chrome/answer/1342714?hl=ko


'DEVELOPMENT > 보안' 카테고리의 다른 글

XSS 공격 패턴  (0) 2009.04.19
[MD5] APS , JAVASCRIPT MD5 암호화 함수  (0) 2008.07.25

AppData 폴더에는 앱 설정, 파일 및 PC의 앱 관련 데이터가 포함되어 있습니다. 기본적으로 이 파일은 파일 탐색기에서 숨겨져 있으며 Local, LocalLow, Roaming이라는 세 개의 숨겨진 하위 폴더를 가지고 있습니다.

  • Roaming. 이 폴더(%appdata%)에는 사용자가 도메인에 있는 경우 등 PC 간에 사용자 프로필로 이동할 수 있는 데이터가 포함되어 있습니다. 이 데이터에는 서버와 동기화할 수 있는 기능이 있기 때문입니다. 예를 들어 도메인에서 다른 PC에 로그인하는 경우 사용자 웹 브라우저의 즐겨찾기 또는 책갈피를 사용할 수 있습니다.

  • Local. 이 폴더(%localappdata%)에는 사용자 프로필로 이동할 수 없는 데이터가 포함되어 있습니다. 일반적으로 이 데이터는 PC와 관련되어 있거나 서버와 동기화하기에 너무 큽니다. 예를 들어 보통 웹 브라우저는 여기에 임시 파일을 저장합니다.

  • LocalLow. 이 폴더(%appdata%/…/locallow)에는 이동할 수 없는 데이터가 포함되어 있지만 액세스 권한 수준이 더 낮습니다. 예를 들어 보호 모드나 안전 모드에서 웹 브라우저를 실행 중인 경우 앱에서는 LocalLow 폴더의 데이터에만 액세스할 수 있습니다.

Local, LocalLow 또는 Roaming 폴더 중 앱 정보를 저장할 위치는 앱에서 선택합니다. 대부분의 데스크톱 앱은 기본적으로 Roaming 폴더를 사용하지만 대부분의 Windows 스토어 앱은 기본적으로 Local 폴더를 사용합니다

'DEVELOPMENT' 카테고리의 다른 글

로컬 jar 파일 maven porject에 추가하는 법  (0) 2017.04.25
hsqldb 사용하기  (0) 2016.07.23
Git  (0) 2013.12.30
dxf file format  (0) 2012.08.16
XSLT 빠른 가이드  (0) 2012.01.13

서버를 운영하다 보면 여러가지 이유때문에 서버가 다운되는 경우가 발생을 하게 됩니다. 대부분의 경우 톰캣 스크립트를 통해 서버를 재시작 시켜주기만 하면 되는 간단한 작업이지만, 휴가를 가거나 오랜기간 컴퓨터앞에 앉아 있을 수가 없게 되었을때 서버 다운이 발생하면 속수무책으로 당할수 밖에 없습니다. 그리고 이런 문제가 자주 발생하게 된다면 사용자들은 해당 서비스를 신뢰할수 없게 될것입니다. 이런 때를 대비해서 쉘 스크립트를 통해 톰켓 서버의 상태를 체크 하여 서버가 다운되었을때 재실행 시키는 스크립트를 작성하고,CRONTAB을 이용하여 주기적으로 서버의 상태를 체크하게 하면 그나마 나은 서비스가 될수 있을 것입니다. 아래의 스크립트 내용은 톰켓의 상태를 체크하여 프로세스가 죽어 있으면 스크립트를 실행하여 서버를 재시작 시키는 스크립트 입니다.

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
 
export JAVA_HOME=사용자들의 JAVA_HOME
export PATH=$PATH:$JAVA_HOME/bin
export CATALINA_HOME=톰켓 설치 위치
export PATH=$PATH:$CATALINA_HOME/bin
 
if [ -z "`ps -eaf | grep java| grep tomcat`" ]; then
        $CATALINA_HOME'/bin/startup.sh'
        END_TIME=`date +%m/%d' '%H:%M:%S`
        echo "["$END_TIME"] tomcat restart.."
fi

기본적으로 JAVA_HOME같은 환경변수들은 JDK를 설치할때 세팅을 해줌에도 불구하고 스크립트에서 다시 export 시키는 이유는 crontab에서 스크립트를 실행하면 .bash_profile이나 /etc/profile 에 JAVA_HOME, PATH같은 환경변수를 선언해 두었더라도 환경변수를 읽을 수 없어 톰캣실행이 잘 되지 않습니다. 그렇기 때문에 톰켓을 실행시키기 위한 필수 환경변수들을 스크립트에 다시 한번 선언해 주어야 합니다. 이후 해당 스크립트를 CRONTAB에 등록하면 되는데, CRONTAB에 스크립트를 등록하는 방식은 다음과 같습니다.

1
2
3
$ crontab -e
##vi 에디터가 실행되면 다음의 내용을 추가합니다.
*/5 * * * * /스크립트 경로/tomcat_checker.sh >> /data/log/tomcat-restart.log 2>&1

따로 cron expression은 설명하지 않겠습니다. 위의 뜻은 5분마다 tomcat_checker.sh 스크립트를 실행시키고 그에 따른 결과 로그를 tomcat-restart.log에 append(>>) 하겠다는 뜻입니다. 위와 같이 설정한 후 root 권한으로 crontab을 재시작 시키면 crontab이 적용되게 됩니다.

1
2
$ su
# /sbin/service crond restart

그리고 crontab -l 명령어로 해당 crontab에 스케줄러가 잘 등록이 되었는지 확인 하면 됩니다.  


[원문출처] http://krespo.net/160

'DEVELOPMENT > Server' 카테고리의 다른 글

wildfly jsp 동적으로 변경사항 적용하기  (0) 2017.12.02
windows 10 원격지원 허용 및 포트 변경  (0) 2016.06.15
SVN 사용법  (0) 2014.04.13
Tomcat Context 생성  (0) 2014.04.10
JEUS 사용법  (0) 2013.07.12

서버중 외부로 나가는 트래픽이 막혀있는 서버가 있다면 프록시를 통해 외부로 나가는 요청을 할수가 있습니다.


1. 로그인 세션 동안만 유지되는 방법

텔넷이나 ssh에 로그인 되어있는동안만 프록시를 사용하고 있다면 다음과 같이 사용하면 됩니다.

1
2
3
4
5
6
# 프록시 서버 설정
$ export http_proxy=http://www.yourproxyserver.com:port
$ export https_proxy=http://www.yourproxyserver.com:port
#프록시서버 해제
$ unset http_proxy
$ unset https_proxy

2. 로그인 세션이 종료된 후에도 프록시를 유지시키는 방법

1
2
3
4
5
6
7
8
9
# 여기서는 .bashrc에 작업했지만 .profile, .bash_profile, .bashrc_profile 어디에 설정해도 동일합니다.
$ vi ~/.bashrc
 
#아래내용 추가
export http_proxy=http://www.yourproxyserver.com:port
export https_proxy=http://www.yourproxyserver.com:port
# 저장후
 
$source ~/.bashrc

이후 wget이나 curl로 외부로 요청이 되었을때 데이터를 제대로 가져오면 프록시 설정이 제대로 된것입니다.

1
2
3
$ wget www.daum.net
#혹은
$ curl -0 www.daum.net


[원문출처]http://krespo.net/188

오라클에서 데이터를 저장하다 보면 한 테이블 내에 부모 자식 관계(상하위 관계)로 표현하는 데이터가 발생될 때가 있다. 예를 들어

게시판 ↳ 공지사항 게시판 ↳ 사용자 게시판

와 같이 메뉴를 저장하는 테이블이 있다면 상위 게시판이라는 메뉴는 하위에 공지사항 게시판 메뉴, 사용자 게시판 메뉴를 하위로 가진다면, 데이터 구조는 다음과 같이 생성될 것이다.

MENUIDNAMEURLPARENTMENUID
1공지사항 게시판/notice.html2
2게시판/index.htmlnull
3사용자 게시판/user.html2

만약 쿼리를 상위 메뉴 데이터를 먼저 나오게 하고 그 뒤에 하위 메뉴들을 나오게 하려면 어떻게 해야할까? 이때 Oracle에서는 start with, connect by prior를 사용하여 데이터를 셀렉트 할수 있다.

1
2
3
4
5
6
SELECT
    menuid, name, url, parentmenuid
FROM menu
START WITH parentmenuid is null /*상위(부모)의 조건을 명시*/
CONNECT BY PRIOR menuid = parentmenuid  /*상위의 키와 하위의 키를 열결시킴*/
ORDER SIBLINGS BY menuid ASC;   /*하위데이터 정렬 조건*/

이렇게 쿼리를 사용하게 되면 다음과 같이 셀렉팅이 된다.

MENUIDNAMEURLPARENTMENUID
2게시판/index.htmlnull
1공지사항 게시판/notice.html2
3사용자 게시판/user.html2

[원문출처]http://krespo.net/171

Oracle 11g에 LISTAGG라는 function이 추가되었습니다. 이 function은 group by로 그룹핑된 문자열 row들을 하나의 컬럼으로 결합시키는 역할을 하게 됩니다. 간단하게 예를 들어보도록 하겠습니다.



 DEPTNO

 NAME

 1

 김태희

 1

 전지현

 2

 성나정

 3

 고아라 


위의 데이터에서 부서번호(DEPTNO)가 1인 사원들의 이름을 한번에 뽑고 싶을 경우에는 아래와 같은 쿼리를 사용하면 됩니다.

1
2
3
4
5
6
SELECT
    deptno, LISTAGG(name, ',') within group (order by name) name
FROM
    test_tb
where deptno = 1
group by deptno;

LISTAGG(결합시킬 컬럼, ROW 사이의 결합 문자) within group (해당 그룹 사이의 정렬조건)

으로 간단하게 사용할 수 있습니다


위 쿼리를 실행하면 결과값은 아래처럼 나오게 됩니다.


DEPTNO 

NAME 

김태희, 전지현 


[원문출처]http://krespo.net/195




-- 패스워드 기간 확인
select * from dba_profiles where profile = 'DEFAULT';

-> Password life cycle 이 180 이 기본 설정임.

alter profile default limit password_life_time unlimited;
-> 기간제한 없이 변경해 준다.


alter user 계정이름 identified by 패스워드 ;

-> 계정에 대한 패스워드를 다시 설정해 준다.


--계정 잠금

ALTER USER "계정명" ACCOUNT LOCK;

 

--계정 잠금 해제

ALTER USER "계정명" ACCOUNT UNLOCK;

 

--계정 비밀번호 만료

ALTER USER "계정명" PASSWORD EXPIRE;

 

--계정 비밀번호 만료해제 or 변경

ALTER USER "계정명" IDENTIFIED BY "비밀번호";


-- 계정 조회

SELECT USERNAME, ACCOUNT_STATUS, EXPIRY_DATE, PROFILE FROM DBA_USERS

WHERE ACCOUNT_STATUS = 'OPEN';


-- 만료기간 무제한 profile 변경

ALTER PROFILE DEFAULT LIMIT

  FAILED_LOGIN_ATTEMPTS UNLIMITED

  PASSWORD_LIFE_TIME UNLIMITED;


-- 만료기간 제한 profile 변경

ALTER PROFILE DEFAULT LIMIT

  FAILED_LOGIN_ATTEMPTS 20

  PASSWORD_LIFE_TIME 365;

  

--Profile 변경

SQL> ALTER PROFILE default LIMIT

  2  > FAILED_LOGIN_ATTEMPTS 3

  3  > PASSWORD_LIFE_TIME 60

  4  > PASSWORD_GRACE_TIME  10; 

  

-- profile 파라메터 설명

PASSWORD history    : 이전 암호를 기억해 놓았다가 다음에 변경시 동일한 암호사용을 금지함 password_reuse_time : 동일한 password를 적용한 기간동안 사용금지 

password_reuse_max : 입력된 value값만큼만 사용가능한 횟수를 제한 ex: 3이라고 입력하면 3번만 사용가능 password_life_time     : password 생명주기 ex : 30 -> 30일마다 변경해야함 

password_grace_time : password 변경 만료 알림을 value일 전부터 알림 

failed_login_attempts   :password 입력실패시 재시도 가능횟수 최종 실패시 계정 lock걸림 

password_lock_time   : lock걸렸을때 value값만큼 잠겨있음 1일단위임 1/24는 1시간 1/1440은 1분 

password complexity verification(패스워드 복잡성)password설정시 제약조건


-- 파라미터 정보

Parameter: FAILED_LOGIN_ATTEMPTS

Default Setting:  10

Description:  Sets the maximum times a user login is allowed to fail before locking the account.

 

Parameter: PASSWORD_LIFE_TIME

Default Setting:  180

Description:  Sets the number of days the user can use his or her current password.


[출처] http://aspopark.tistory.com/31

java.lang.reflect를 이용하면 우리가 원하는 클래스에 대한 invoke가 가능하다는 것은 알고 있을 것이다.

하지만 classpath에 등록안되어진 클래스들에 대해서는 어떻게 할 것인가? 


일일이 사용자에게 클래스 패스를 설정하게 할수만은 없는 일이다. 


보통의 엔진들을 보게 되면 install되어진 디렉토리의 위치만을 세팅하도록 하고 있다. 

set JAVA_HOME이라던지 

set ANT_HOME이라던지.. 


쉘스크립트에 의하여 그러한 것들을 정의하여 java process를 띄우곤 하는데 그러면 

내가 ant.jar등을 등록하지 않았음에도 불구하고 해당 애플리케이션들이 잘 작동하는 이유는 무엇일까? 

그것은 바로 ClassLoader에 숨겨져 있다. 

아래에서 보여지는 샘플코드는 classpath 프로퍼티에 등록이 되어지지 않은 클래스들에 대한 조작을 할 것이다. 


그렇게 함으로서 이 글을 읽는 당신이 만든 애플리케이션이 별다른 클래스로딩 정책 없이도 작동이 될수 있겠다. 

그러려면 또한 잘 알아야 하는것이 reflection API이거늘... 

이부분에서는 그러한 것을 생략하고 URLClassLoader를 이용하여 디렉토리나 jar파일을 등록하여 가져오는 

방법을 설명하도록 하겠다. 


ClassLoader클래스는 이미 1.0API부터 존재해왔으면 URLClassLoader는 1.2에 새롭게 추가된 클래스이다. 

우리가 사용하는 파일시스템이 URL이란 이름하에 조작이 될 수 있다는 것을 우선 명심하기 바란다. 

왜냐면 file:/// 이란 URI를 사용하기 때문이다. 


아래에서는 특정한 디렉토리 안의 jar파일에 대한 class loading샘플을 보여준다.. 

  1. import java.io.*;
  2. import java.net.*;
  3. public class ClassLoading {
  4.   public static void main(String [] args) throws Exception {
  5.     // Create a File object on the root of the directory containing the class file
  6.     File file = new File("D:/_Develop/jmxSamples/customMBean/log4j-1.2.8.jar");    
  7.     try {
  8.       // Convert File to a URL
  9.       URL url = file.toURL();          // file:/D:/_Develop/jmxSamples/customMBean/log4j-1.2.8.jar
  10.       URL[] urls = new URL[]{ url };
  11.       System.out.println(urls);
  12.        
  13.       // Create a new class loader with the directory
  14.       ClassLoader cl = new URLClassLoader(urls);
  15.       System.out.println(cl);
  16.        
  17.       // Load in the class; Logger.class should be located in
  18.       // the directory file:/D:/_Develop/jmxSamples/customMBean/log4j-1.2.8.jar
  19.       Class cls = cl.loadClass("org.apache.log4j.Logger");
  20.       System.out.println(cls);    
  21.     } catch (MalformedURLException e) {
  22.       e.printStackTrace();
  23.     } catch (ClassNotFoundException e2) {
  24.       e2.printStackTrace();
  25.     }  
  26.   }
  27. }




위에서 보는 것처럼 디렉토리를 설정하거나 특정 jar파일을 사용할 수 있도록 작성한다. 

특정파일이 가르키지 않으면 해당 디렉토리의 class파일들을 package형태로 참조하도록 할 수 있는데 

해당 디렉토리에 대한 클래스 로딩 샘플을 아래와 같다. 

  1. import java.io.*;
  2. import java.net.*;
  3. public class ClassLoading {
  4.   public static void main(String [] args) throws Exception {
  5.     // Create a File object on the root of the directory containing the class file
  6.     File file = new File("D:/_CVSDevelop/jca_hello_adapter/build/classes");
  7.      
  8.     try {
  9.       // Convert File to a URL
  10.       URL url = file.toURL();          // file:/D:/_CVSDevelop/jca_hello_adapter/build
  11.       URL[] urls = new URL[]{ url };
  12.       System.out.println(urls);
  13.        
  14.       // Create a new class loader with the directory
  15.       ClassLoader cl = new URLClassLoader(urls);
  16.       System.out.println(cl);
  17.        
  18.       // Load in the class; Test.class should be located in
  19.       // the directory file:/D:/_CVSDevelop/jca_hello_adapter/build/classes/com/bea/jca/test/Test
  20.       Class cls = cl.loadClass("com.bea.jca.test.Test");
  21.       System.out.println(cls);
  22.      
  23.     } catch (MalformedURLException e) {
  24.       e.printStackTrace();
  25.     } catch (ClassNotFoundException e2) {
  26.       e2.printStackTrace();
  27.     }  
  28.   }
  29. }
  30.  

위 예제는 classpath의 루트로 잡은 디렉토리를 기준의 package형태로 설정되 파일을 로딩하여 사용할수 있도록 한다. 


이 이후의 코딩에는 class가 newInstance를 취한 후 method를 invoking해야 하는 과정을 거치게 되는데

한 가지 주의할 점은 해당 클래스를 반드시 reflection API를 이용하여 호출해야 한다는 점이다. 


대략 아래의 코드정도를 이용하여 main 메소드등을 호출하는 클래스를 작성할 수 있을 것이다. 

  1. public void invokeClass(String name, String[] args)
  2.     throws ClassNotFoundException,
  3.           NoSuchMethodException,
  4. {
  5.     Class c = loadClass(name);
  6.     Method m = c.getMethod("main"new Class[] { args.getClass() });
  7.     m.setAccessible(true);
  8.     int mods = m.getModifiers();
  9.     if (m.getReturnType() != void.class || !Modifier.isStatic(mods) ||
  10.         !Modifier.isPublic(mods)) {
  11.         throw new NoSuchMethodException("main");
  12.     }
  13.     try {
  14.         m.invoke(nullnew Object[] { args });
  15.     } catch (IllegalAccessException e) {
  16.         // This should not happen, as we have disabled access checks
  17.     }
  18. }


[출처]http://www.yunsobi.com/blog/136

linux 환경에서 구동되는 프로그램을 만들었는데 사용자의 요청에 의해서

리눅스가 처음 시작할때 자동으로 프로그램을 실행하도록 요청을 받을때 간단하게 사용합니다.

 

chkconfig 라는 명령으를 통하여 등록을 할 수도 있지만 리눅스의 부팅과정을 이해해야하며

런레벨에 대한 정보도 학습해야 합니다. 리눅스도 잘 모르는 사용자라 하면 복잡하게 느껴질수도 있습니다.

 

하지만 해당 방법은 crontab을 통하여 등록할 수 있으며 사용방법이 간답합니다.

 

사용법

 

1. 프로그램이 실행하고자 하는 계정으로 로그인 한 후 아래 명령어를 입력하여 편집모드로 들어갑니다.

crontab -e 

 

2. @reboot 명령을 통하여 실행하고 하는 명령어를 입력합니다.

예를 들어서 부팅시 어떤 프로그램을 를 자동으로 실행하기 위한 명령어를 등록하기 위해서서 아래와 같이 입력하였습니다.

 

@reboot /home/test/test/programstart.sh 

 

3. 저장한 후 vi를 닫습니다.

 

crontab은 일반적으로 사용하는것 외에 특정 몇가지 활성화 매계변수가 존재하는데 아래와 같은 것들이 있습니다.

직접 쳐도 되지만 간단하게 사용할 수도 있으니 유용하게 사용되었으면 합니다. 

@reboot = run at boot and reboot only

@yearly  = run at midnight Jan 1 each year (equiv to 0 0 1 1 *)
@annually  = run at midnight Jan 1 each year (equiv to 0 0 1 1 *)
@monthly  = run at midnight on the first day of each month (equiv to 0 0 1 * *)
@weekly  = run at midnight each Sunday (equiv to 0 0 * * 0)
@daily  = run at midnight each day (equiv to 0 0 * * *)
@ midnight  = run at midnight each day (equiv to 0 0 * * *)

@ hourly = run on the first second of every hour (equiv to 0 * * * *) 

crontab format:
{activation parameters} {command #1} ; {optional command #2} ; {optional command #3} ; {etc, commands end on the line ending}

Example:
* * * * * ./folding
This would cause folding to be launched every minute, from your home folder. Very bad, you would end up with 60 copies running by the end of an hour.

Commands are shell commands. Separate multiple commands with a semicolon ";" and end on the line ending.

Activation parameters:
@reboot = run at boot and reboot only
@yearly = run at midnight Jan 1 each year (equiv to 0 0 1 1 *)
@annually = run at midnight Jan 1 each year (equiv to 0 0 1 1 *)
@monthly = run at midnight on the first day of each month (equiv to 0 0 1 * *)
@weekly = run at midnight each Sunday (equiv to 0 0 * * 0)
@daily = run at midnight each day (equiv to 0 0 * * *)
@ midnight = run at midnight each day (equiv to 0 0 * * *)
@ hourly = run on the first second of every hour (equiv to 0 * * * *)
- or -
1 2 3 4 5 = specific time tags
- where -
1 = Minute (of hour) to activate [0-59]
2 = Hour (of day) to activate [0-23]
3 = Day (of month) to activate [1-31 ... 29,30,31 may not activate during all months]
4 = Month (of year) to activate [1-12 or 3-letter names "Jan,Feb,Mar"]
5 = Weekday to activate [0-7 or 3-letter names "Mon,Tue,Wed"]

If 3-letter names are used on Month/Weekday instead of numbers, they are case-insensitive. "Mon" and "mON" are equally acceptable. If numbers are used for the weekday, "0" and "7" are both Sunday and are interchangeable.

Time tags are separated by spaces. Do not use spaces within a tag, this will confuse cron. All five tags must be present. They are a logical AND of each other. There is another space between the last time tag and the first command.

A time tag can be a wildcard "*", which means "all". It can be one value, several values, a range, or a fractional range.

Examples for the Hour column:
8 = one value: execute in the 8 AM hour
5,6,9 = multiple values: execute in the 5, 6, and 9 AM hours
5-8 = range: execute in each hour between 5-8 AM (inclusive)
*/2 = fractional: execute in every other hour. 0 (midnight), 2AM, 4AM, 6AM, etc
3-12/3 = fractional range: execute in every third hour between 3AM and 12PM: 3AM, 6AM, 9AM, 12PM

Example:
5 */3 * * 1-5 cd "desktop/fold1"; ./fold &
This will launch on the 5-minute mark, every third hour, every day, every month, but only on days of the work week (Mon-Fri). It cd's to the Desktop/Folding folder #1, then launches the launch script in nohup mode so folding will keep running.