2011-11-24 36 views
15

Bạn có thể chạy một kịch bản scala như một kịch bản shell linux:Scala như một kịch bản shell: lọ trên classpath

#!/bin/sh 
exec scala "$0" "[email protected]" 
!# 

println("Hello") 

Trong một kịch bản như vậy tôi cần để tải các lớp từ một nhóm các lọ (mà xảy ra với nằm trong cùng thư mục với tập lệnh). Nếu đây là REPL tôi có thể sử dụng :jar, nhưng điều đó không có sẵn ở chế độ tập lệnh.

Tôi đang cố gắng để thiết lập các thông số -classpath:

#!/bin/sh 
exec scala -classpath '.:./*.jar' "$0" "[email protected]" 
!# 

import javax.media.jai.{JAI, RenderedOp} 

nhưng trình biên dịch chỉ không thể tìm thấy các lớp:

error: object media is not a member of package javax 
import javax.media.jai.{JAI, RenderedOp} 
      ^

Làm thế nào để đưa những lọ?

+1

Sử dụng ' '' sẽ ngăn chặn sự bành trướng glob, vì vậy nó sẽ tìm kiếm một tập tin _named_ '* .jar'. –

Trả lời

9

Đối với một số lý do, glob (*.jar) không hoạt động. Tôi đã có thể để có được những kịch bản đang chạy bằng cách đặt trong tất cả các thư viện bằng tay:

#!/bin/sh 
exec scala -cp lib/jai_codec.jar:lib/jai_core.jar:lib/mlibwrapper_jai.jar $0 [email protected] 
!# 

import javax.media.jai.{JAI, RenderedOp} 

Tôi không biết lý do tại sao glob không hoạt động mặc dù.

Lưu ý rằng trong trường hợp này tôi không có . trong đường dẫn lớp vì bản thân tập lệnh được cung cấp làm đối số. Trong nhiều trường hợp mặc dù bạn sẽ cần phải bao gồm nó:

exec scala -cp .:lib/jai_codec.jar:lib/jai_core.jar:lib/mlibwrapper_jai.jar $0 [email protected] 

Dựa trên this helpful post, tôi có một tiêu đề kịch bản mà kéo trong mỗi lọ trong một thư mục lib, ngay cả khi kịch bản (hoặc thư mục đó trong) là các liên kết tượng trưng.

#!/bin/sh 
L=`readlink -f $0` 
L=`dirname $L`/lib 
cp=`echo $L/*.jar|sed 's/ /:/g'` 
/usr/bin/env scala -classpath $cp $0 [email protected] 
exit 
!# 
  • Dòng đầu tiên biến kịch bản vị trí cho $0 vào vị trí thực tế của nó trên đĩa, mở rộng liên kết tượng trưng.
  • Dòng thứ hai loại bỏ tên kịch bản và cho biết thêm /lib
  • Dòng thứ ba tạo ra một biến cp với tất cả các lọ ngăn cách bởi :
  • Dòng thứ tư chạy scala, bất cứ nơi nào nó có thể được.
  • Dòng thứ năm thoát. Điều này có lẽ là không cần thiết, nhưng nó làm cho tôi cảm thấy tốt hơn.
+1

'lib/*. Jar' không hoạt động, nhưng này là: 'lib/*' –

+2

Shell globs chỉ hoạt động khi chúng khớp với tên tập tin. Điều này sẽ không hoạt động trong đường dẫn vì ':' là một ký tự tên tệp hợp lệ. Ngoài ra, khi các bóng tối phù hợp, chúng sẽ xuất ra một danh sách các tên tập tin _space-separated_. –

+0

Thêm tùy chọn biên dịch -savecompiled để làm cho tập lệnh thực thi nhanh hơn sau lần đầu tiên. –

10
exec scala -classpath ./*.jar $0 [email protected] 

sẽ làm việc

+2

+1, nhưng không bao gồm. –

+3

Không, nó không hiệu quả với tôi. Câu lệnh import không thành công với một thông báo lỗi như: 'error: object jai không phải là thành viên của package com.sun.media' Lớp đang nghi vấn chắc chắn nằm trong một trong các lọ, tôi đã kiểm tra. –

+0

Hm. Tôi không biết. Nó chỉ làm việc cho tôi. Tôi đã kiểm tra với một số jar – viktortnk

4

tôi khuyên bạn nên sử dụng SBT thay vì để xử lý nó. Xem scripts wiki, điều này giải thích làm thế nào để làm điều gì đó như thế này:

#!/usr/bin/env scalas 
!# 

/*** 
scalaVersion := "2.9.0-1" 

libraryDependencies ++= Seq(
    "net.databinder" %% "dispatch-twitter" % "0.8.3", 
    "net.databinder" %% "dispatch-http" % "0.8.3" 
) 
*/ 

import dispatch.{ json, Http, Request } 
import dispatch.twitter.Search 
import json.{ Js, JsObject } 

def process(param: JsObject) = { 
    val Search.text(txt)  = param 
    val Search.from_user(usr) = param 
    val Search.created_at(time) = param 

    "(" + time + ")" + usr + ": " + txt 
} 

Http.x((Search("#scala") lang "en") ~> (_ map process foreach println)) 
+2

Điều này làm việc nhưng nó làm cho nó làm cho chạy kịch bản đơn giản mất khoảng 8 giây, mỗi lần, bất kỳ cách nào xung quanh đó để làm cho nó nhanh hơn ngay cả trong chạy tiếp theo? –

+0

@MohamedRagab Tôi nghĩ rằng nó có thể tiết kiệm trên một số công việc được thực hiện, nhưng tôi không chắc chắn. Một JVM nóng có lẽ quan trọng hơn, chẳng hạn như bạn có thể nhận được với [Nailgun] (http://www.martiansoftware.com/nailgun/). –

+0

@DanielCSobral chắc chắn Nailgun sẽ giúp, để hiểu biết của tôi trên đầu của JVM là dưới một nửa thứ hai, và bộ nhớ đệm SBT tiết kiệm một chút thời gian hơn tất nhiên. Nó sẽ là tuyệt vời nếu một số xử lý thực hiện ở đây là tránh nếu không cần thiết, tôi đang chơi với một nỗ lực để kiểm tra đầu tiên trong kịch bản bash sự tồn tại của các tập tin JAR trong bộ nhớ đệm ivy và sau đó thêm chúng vào classpath trực tiếp –

0

Bạn cũng có thể đặt dấu nháy đơn xung quanh classpath với một glob, như thế này:

exec scala -classpath '.:*.jar' "$0" "[email protected]"

0

Để tránh để xác định nghĩa classpath trong mỗi tiêu đề bạn có thể xác định một chức năng mà kết thúc tốt đẹp thực thi scala của bạn trong (ví dụ) .bashrc của bạn và làm cho nó hiển thị đối với phạm vi bên ngoài:

... 
function scala() { 

    PARAMS=("[email protected]") 

    FILENAME=${PARAMS[0]} 
    REMAINING_PARAMS=(${PARAMS[@]:1:${#PARAMS[@]}}) 

    CUSTOM_CLASSPATH_DEF=".:/whatever/*" 
    /path/to/scala -cp "$CUSTOM_CLASSPATH_DEF" -Dscala.color=true "$FILENAME" "${REMAINING_PARAMS[@]}" 
} 

export -f scala 
... 

Bây giờ bạn có thể định nghĩa tiêu đề của bạn như:

#!/bin/bash 
scala "$0" "[email protected]" 
exit 0 
!# 

(Bạn vẫn có thể sử dụng REPL gõ 'scala' từ dòng lệnh)

Các vấn đề liên quan